Skip to content

Troubleshooting

Symptom-first fixes for the problems that come up most. For the underlying model — how errors are surfaced and how keys resolve — see Error handling.

no adapter registered for protocol "..."

Stream or Complete returns this error immediately.

  • Cause: the provider package for the model's protocol was never imported, so no adapter registered itself.
  • Fix: add the blank import for the protocol you use — or llm/all for all built-ins. Imports are by protocol, not by vendor: DeepSeek needs llm/openai, MiniMax needs llm/anthropic.
import (
    _ "github.com/ktsoator/or/llm/openai"    // openai-completions providers
    _ "github.com/ktsoator/or/llm/anthropic" // anthropic-messages providers
)

panic: llm: unknown model "..." for provider "..."

GetModel panics when the provider/model pair is not in the built-in catalog.

  • Cause: a typo, the wrong provider ID, or a model that is not cataloged.
  • Fix: use LookupModel, which returns (Model, false) instead of panicking, and browse the catalog with GetProviders / GetModels.
model, ok := llm.LookupModel("deepseek", "deepseek-v4-flash")
if !ok {
    log.Fatalf("not in catalog; providers: %v", llm.GetProviders())
}

For an endpoint that is not in the catalog, construct an llm.Model by hand and set its BaseURL, Protocol, and Provider.

API key is empty for provider "..."

The request never reaches the provider.

  • Cause: the expected environment variable is unset — or you set the wrong one. Variables are provider-specific, and regional variants differ: MiniMax global reads MINIMAX_API_KEY, but MiniMax CN reads MINIMAX_CN_API_KEY. The error message lists the exact variables that were checked.
  • Fix: set the named variable, pass StreamOptions.APIKey directly, or supply StreamOptions.Env. Confirm which variables a provider expects with APIKeyEnvVars, and which are actually set with FindEnvAPIKeys.
fmt.Println(llm.APIKeyEnvVars("minimax-cn")) // [MINIMAX_CN_API_KEY]
fmt.Println(llm.FindEnvAPIKeys("minimax-cn")) // [] means none is set

The response failed (StopReasonError)

Complete returns a non-nil error, or a stream ends with EventError.

  • Cause: a provider or runtime failure mid-request (auth rejected, rate limit, an unavailable model).
  • Fix: read response.ErrorMessage for the provider's detail. Do not execute any tool calls from a failed response. Transient failures are retried by the SDK; tune with StreamOptions.MaxRetries and Timeout.

The answer is cut off (StopReasonLength)

The text ends mid-sentence.

  • Cause: generation hit the MaxTokens cap.
  • Fix: raise MaxTokens, or continue the turn by appending the partial assistant message and sending again.

Silent truncation or context errors

The model ignores the start of a long conversation, or rejects it outright.

  • Cause: the request exceeded the model's context window. Some providers error; others silently drop the overflow.
  • Fix: call IsContextOverflow(response, model.ContextWindow) and, when it is true, compact or summarize old messages before retrying.

Tool arguments are wrong or incomplete

DecodeToolCall returns an error, or AssistantMessage.Diagnostics reports recovered arguments.

  • Cause: the model produced malformed JSON, or the stream was truncated. The library recovers arguments best-effort and records how in Diagnostics rather than failing the whole response.
  • Fix: before running a tool with side effects, check Diagnostics and decline partial or invalid arguments. On a decode error, return a tool error (result.IsError = true) so the model can correct the call. See the tool-loop checklist.