Documentation
Table of Contents

Common problems

Most problems show up in one of two places. A problem with your code or configuration throws, before any model call. A problem with the model's answer, or with the provider, does not throw: the call returns a result with Success false, and its Issues say what went wrong. result.FailureSummary puts them on one line, and result.Attempts shows each attempt with its own issues. The database methods are the exception: they throw SemanticDatabaseException when no safe statement results (Database queries). License messages are covered in License problems.

The client is not built

Exception and message Cause and fix
InvalidOperationException: "Neither OPENAI_API_KEY nor ANTHROPIC_API_KEY is set." UseProvidersFromEnvironment found neither key in the environment of the process. Set one in the shell, the service or the container that runs the application, not only in your own terminal.
InvalidOperationException: "IntentSharp: configure OpenAIApiKey and/or AnthropicApiKey ..." AddIntentSharp found no provider key in the configuration or the environment (Installation).
InvalidOperationException: "No provider configured." The builder has no primary provider. Call a provider method before Build.
InvalidOperationException: "PrimaryProvider ... is not a known provider." IntentSharp:PrimaryProvider is not OpenAI or Anthropic. Fix the name, or leave it unset.
InvalidOperationException: "PrimaryProvider is OpenAI but no OpenAI key is configured." (or Anthropic) IntentSharp:PrimaryProvider names a provider whose key is not set. Set that provider's key, or change PrimaryProvider.
ArgumentOutOfRangeException An option is out of its range, for example MaxAttempts 0. The message names the option and its range (the client options).
ArgumentException: "A provider named ... is already registered" The primary and the fallback have the same name. Give one of them another name.

A call fails with a provider issue

A provider error ends the call with an issue whose Source is IssueSource.Provider, and whose message names the provider and the HTTP status. Which errors the built-in providers retry, and which go to the fallback provider, is in the table on Providers. A transient error goes to the fallback when one is set, unless FallbackOnTransientErrors is false or the request names a provider.

What the issue says What to do
"rejected the API key (401)" or "(403)" Check the key, and that it belongs to the account and project you expect.
"rejected the request (400)" or "(422)" The provider refused the request itself. Common causes: a model name the account cannot use, a setting the model does not accept, or a request larger than the model's context. The issue holds the provider's own message.
"error 404" Usually a model name that does not exist. Check AnthropicModel, OpenAIModel or the Model of the request.
"rate limit exceeded" The provider's limit for your account. Lower the number of calls at once, add a rate limiter (Memory, cache and rate limiting), or ask the provider for a higher limit.
"Local rate limit for ...: next slot in ...ms exceeds the 30000ms wait budget." Your own rate limiter, not the provider: the call would have waited more than 30 seconds for a slot, so nothing was sent. Raise the limiter's rate or burst (RateLimitPerSecond and RateLimitBurst with AddIntentSharp), or make fewer calls at once.
"service error (5xx)" A failure on the provider's side. Set a fallback provider (Providers).
"transport error" No reply arrived: DNS, a proxy, TLS or the network. Check that the application can reach the provider over HTTPS; a proxy is set on the HTTP client (The HTTP clients).
"returned 200 with a body that is not JSON" Something between you and the provider, such as a proxy or a gateway, answered with a page that is not the provider's reply. Check the base address and the proxy.
"request exceeded the 120s timeout" One attempt took longer than the provider's time limit. Ask for a shorter answer, lower MaxOutputTokens, or raise the provider's timeout (Providers).
"The model declined to answer this request." The model refused, and the call ends at that attempt. Check the intent and the input.
"The response was cut off by the output token limit." The answer needs more tokens than MaxOutputTokens; the next attempt carries the finding. Raise the limit for the request, or ask for less.

Two more issues come from the limits you set, with Source IssueSource.Guardrail: "The request exceeded its ...s time budget." (DefaultTimeout, or Timeout on the request) and "Model call ceiling of ... reached" (MaxModelCalls). Raise the limit, or ask for less per call.

A request that names a provider the client does not have, in AIRequestOptions.Provider, throws ArgumentException instead, listing the names it has.

The input is too large

A call whose serialized input is longer than MaxInputChars (200,000 characters by default) throws ArgumentException before any model call. The message gives the input's length and the limit. IntentSharp never cuts the input short to make it fit. The limit counts the input only, not the intent or the examples.

  • Send only what the model needs. The input is sent as JSON with every public property of the object, so pass a smaller object with the fields the intent uses.
  • Split the work into several calls. A collection method sends the whole list in one request, so a long list goes in batches, and a long document in parts.
  • Raise MaxInputChars, within the context size of your model and with each call's cost in mind.

An input under the limit can still be too large for the model's context. The provider then refuses the request with a 400 issue.

A result type gets no strict schema

For most result types the model must answer in a strict JSON schema made from your type. Some types cannot be expressed that way, such as a dictionary or object; Typed output lists them. For such a type the model is asked for JSON without the strict schema. The reply is still parsed and checked against your type, but the provider no longer holds the answer to the shape, so only the checks catch a wrong shape. IntentSharp does not warn about it.

  • Replace a dictionary with a list of records, for example List<Price> where Price has Sku and Amount.
  • Replace object or a JSON type with a concrete type.
  • Mark a property the model does not need with [JsonIgnore].
  • When the shape is only known at run time, pass a JSON schema instead of a type.

Typed output lists the types that get a strict schema and the options that shape a reply.

An intent file does not load or does not apply

Problem Cause and fix
DirectoryNotFoundException when the catalog is created The folder is not where the catalog looks. A relative folder is read from the application's output folder (AppContext.BaseDirectory), not from the current directory. Copy the folder to the output, as step 3 of the quick start shows.
IntentNotFoundException: "No intent named ... is in the catalog" The name is not loaded. Check the spelling (names ignore case; the message suggests close names), and that the file name ends in .intent.yaml, .intent.yml or .intent.json. When the intent's file has a problem, the message includes it.
An edit does not take effect The edited file has a problem, so the intent loaded before stays in use. Each problem is logged as a Warning with the file and the line, and listed in catalog.Current.Problems. Also check that you edited the copy the application reads, in the output folder, not the one in the project.
"Duplicate intent name" in the problems Two files define the same name. The file that comes first in path order wins, and the other definition is ignored.
IntentDisabledException The file says enabled: false.
IntentShapeMismatchException The file's result shape cannot be returned as the type you asked RunAsync<T> for. Ask for the type the shape describes; any shape can be run as JsonNode.
IntentSharpException: "names the validator ..." or "names the type ..., which is not registered" The file names a code validator or a .NET type that the runtime does not know. Register it with AddIntentValidator or AddIntentType (Running intents from files).

Each of these throws before any model call. The intent files guide describes the format, and the roadmap lists the known limits of reloading files.

A call without a client throws

value.AIAsync<T>("...") and the other methods that take no client find the client made ambient with client.AsAmbient(), for the current async flow. Outside such a scope they throw InvalidOperationException. Pass the client to the method, or open the scope around the call. There is no process-wide default client.