Skip to main content

Troubleshooting

What a symptom usually means. For what each error kind is, see Errors.

At runtime​

Building the client​

SymptomUsual cause
Config: "plain HTTP to a host that is not loopback"The URL is http:// to another machine. Use https://, or .allow_http() for a trusted network
Config: "an https URL needs the tls or the tls-aws-lc feature"default-features = false without either
Config: "the API key variable ... is not set"api_key_env names a variable the process does not have. svir reads no .env file
Config: "http() must be called before layers are added"Move .http(backend) above .layer(..) and .wrap(..)
Config: "a header name is not valid"A name given to .header(..) has a space or another character a header name cannot have
Config: "the header ... is set by svir, not by the caller".header(..) named authorization, content-type, content-length, accept, host, transfer-encoding, or connection. The Bearer key goes through api_key
Config: "the value of header ... is not valid"The value has a line break, another control character, or text that is not ASCII. Often a value read from a file with its trailing newline: trim it
A panic elsewhere: "no process-level CryptoProvider available"Two rustls providers are compiled in: svir's tls brought ring next to another crate's aws-lc-rs. Take svir with tls-aws-lc; see Features and TLS

Sending​

SymptomUsual cause
Transport, and is_unsent() is trueNothing listens at the URL: the server is not running, or the port is wrong
Unsupported, detail "HTTP 404"The base URL points somewhere that is not the API (a path too many, a web UI), or the server does not know the model. server_message() usually says which
Unsupported, detail "HTTP 400" or "HTTP 422"The server rejected the request. Read server_message(). Common: a model without tool or image support, or a message the server's chat template cannot take
ContentFilter, detail "HTTP 400"Azure OpenAI's content filter blocked the prompt. Nothing was generated, but the evaluation was billed: change the prompt rather than send it again
Unsupported: "the response is not an event stream"A success status with HTML or JSON: a gateway page, or an endpoint that ignores stream
ContextOverflow before anything was sentcontext_tokens is set and the body's bytes plus max_tokens exceed it. Bytes overestimate images by far
ContextOverflow from the serverThe conversation outgrew the context. Some servers say it inside a 200 stream; svir reports both the same way
Unsupported: "a tool call is required, and the request offers no tools"ToolChoice::Required on a request with no tools. Add them with .tool(..) or .tools(&toolbox)
Unsupported: "a call is required of a tool the request does not offer"ToolChoice::tool(name) names a tool that is not in the request: a typo, or a tool not added
Unsupported, detail "HTTP 400", on a request with a tool choice or a response formatThe server does not take it, and svir never sends the request without it. LM Studio rejects a named tool (use Required with that one tool) and ResponseFormat::Json (use a Schema). OpenAI rejects Json unless the messages say "JSON"; OpenAI and Azure OpenAI reject a strict schema whose objects do not list every property as required with additionalProperties: false
Attachment: "an image has no media type"An extension other than png, jpg, jpeg, gif, webp. Add .media_type(..)
Attachment: "a text file is not UTF-8"TextFile is for text. Send an image as Image; convert anything else first
Attachment: "a text file is not the escaped length it declares"TextFile::escaped_len declared a length the file cannot have, or one text in memory does not have. Measure the whole file with svir::body::escaped_len
Attachment: "an attachment changed after the body was built, or is not the length it declares"The file was written to between measuring and sending, or its declared escaped_len is wrong

While the answer streams​

SymptomUsual cause
Unsupported: "a delta field outside the protocol", or another "outside the protocol"Strict decoding met something svir does not know. Read what the server sends (the relay example prints it); .lenient() skips such fields
Unsupported: "a finish reason outside the protocol"The server stopped for a reason svir does not know (a filtered answer is FinishReason::ContentFilter, not this). Lenient mode does not change this
Protocol: "an answer that is both content and a refusal", or "a refusal with tool calls"The server contradicts itself about what the answer is. Report it, with the raw stream; lenient mode does not change this
Timeout: "the server sent no response" or "the response stalled"Silence for longer than the idle timeout (5 min by default). A local model on a long prompt can take longer; raise idle_timeout
Timeout from a Timeout::first_token layer on a local modelThe deadline is shorter than the model needs to read the prompt
TruncatedStreamThe connection was cut: a gateway's own timeout, or a server that crashed or unloaded the model
ResponseLimitA response over 64 MiB, an event over 256 KiB, or more than 64 tool calls. Raise Limits if that is expected

The answer itself​

SymptomUsual cause
done.usage is NoneThe server does not report usage, or it rejected the field and the client stopped asking
done.text starts with blank linesThe server left them after the reasoning. Trim for display
done.text is empty and finish is LengthReasoning used the whole output budget. Raise max_tokens, or lower the effort
done.text is empty and finish is ToolCallsNot a failure: the model is waiting for tool results
finish is ContentFilter, though the whole answer streamedAzure's asynchronous content filter vets the answer after streaming it, and blocked part of it. Withdraw the text the user was shown
finish is RefusalThe model would not answer, and done.text is its refusal: show it. Asked for a format, OpenAI's models refuse rather than give an answer they will not put in it
parse fails: "the answer is not whole: it finished with Length"The output limit cut the answer off: raise max_tokens. With another finish named, the text is not the answer asked for either
parse fails, and done.text is emptyLM Studio, with reasoning on, sent the JSON as reasoning. Add .reasoning(Effort::Off)
parse fails on an answer that looks rightThe type and the schema disagree, or no response format was set and the model wrapped the JSON in prose or a code fence. Derive the schema from the type with Schema::of
The model never calls a toolThe model has no tool support, or the description does not say when to use the tool
The model answers without the call tool_choice requiredThe server took the choice and did not keep it, as LM Studio does with Required. svir does not check: test done.calls
A loop with a required tool call never ends with an answerThe choice stays on the request every turn. Set .tool_choice(ToolChoice::Auto) with the results
The next request after a tool call is rejectedThe assistant turn or a result is missing: request.assistant(done).tool_results(results)
The same answer, whatever model is namedSome local servers answer with the loaded model when they do not know the ID. List the models
A request for one model is slow once, then fastA local server loaded the model on the first request

At compile time​

The compiler saysCause
No variant System on RoleThe system prompt is Request::system(..)
Cannot create a non-exhaustive struct with a struct expressionUse the constructor: Request::new, Tool::new, ToolResult::new, ToolResult::error, Schema::new, Usage::new
Non-exhaustive patterns on Event, ErrorKind, FinishReason, Part, ToolChoice, ResponseFormatAdd a wildcard arm
Use of moved value: requestThe builder takes self. Write request = request.user(..), and pass &request to complete and stream
No method add on ToolsEnable svir's schemars feature, or use add_tool with a schema
No function of on SchemaEnable svir's schemars feature, or write the schema with Schema::new
T: DeserializeOwned is not satisfied, from parseThe type does not derive Deserialize, or borrows: parse returns an owned value, so a field is a String, not a &str
The trait JsonSchema is not implementedYour schemars is not version 1, so its derive is a different trait
Cannot find Trace in svir::layerEnable the tracing feature
Cannot find Client in svirdefault-features = false turned the client feature off
Layer, Next, Retry, or Decoder not foundThey are not in the prelude: svir::layer::.., svir::openai::chat::..
Mismatched types: expected Client<..>, found ClientA client with a custom backend is Client<Backend>; name the type, or be generic over B: svir::http::Backend
A future is not Send, in a Layer or Toolbox implSomething that is not Send (an Rc, a std::sync::MutexGuard) is held across an .await
Expected ToolResult, found Result<..> in Toolbox::callcall returns a result for the model, never an error: turn the failure into ToolResult::error(&call.id, message)