moeru-ai/airi · warning
[llm] Auto-disabling tools for "${key}" due to tool-related
Error message
[llm] Auto-disabling tools for "${key}" due to tool-related error What it means
The chat LLM streaming wrapper caught an error from the provider stream that core-agent's isToolRelatedError() matched (a provider 4xx complaining about the tools/tool_choice parameters, e.g. 'tools is not supported' or an unknown tool-schema error). It then permanently records toolsCompatibility[key] = false for that provider so subsequent requests omit tools, and the failure is not rethrown for this class.
Source
Thrown at packages/stage-ui/src/stores/ai/chat-llm/llm.ts:41
const runStream = () => coreStreamFrom({
model,
chatProvider,
messages,
options: {
...streamOptions,
toolsCompatibility: toolsCompatibility.value,
contentArrayCompatibility: contentArrayCompatibility.value,
},
builtinToolsResolver,
})
try {
await runStream()
}
catch (err) {
if (isToolRelatedError(err)) {
console.warn(`[llm] Auto-disabling tools for "${key}" due to tool-related error`)
toolsCompatibility.value.set(key, false)
}
// NOTICE:
// Auto-degrade content-part arrays to plain strings on the next attempt
// when the provider returned the Rust/serde-style "expected a string"
// 400. We retry once inline so the user's failing turn recovers without
// requiring them to resend; subsequent calls reuse the cached degrade.
// See: https://github.com/moeru-ai/airi/issues/1500
if (isContentArrayRelatedError(err) && contentArrayCompatibility.value.get(key) !== false) {
console.warn(`[llm] Auto-disabling content-part arrays for "${key}" and retrying once`)
contentArrayCompatibility.value.set(key, false)
await runStream()
return
}
throw err
}
}
View on GitHub (pinned to 677329427f)
Solutions
- Verify the provider/model actually supports function/tool calling; pick a tools-capable model if you need tools.
- Update the local OpenAI-compatible server to a build that implements the tools parameter.
- Clear the persisted/remembered toolsCompatibility entry after fixing the server so tools are retried.
- If tools are optional, accept the degraded mode — chat continues without tool use for that provider.
Defensive patterns
Strategy: fallback
Try / catch
try {
await runStream()
}
catch (err) {
if (isToolRelatedError(err)) {
toolsCompatibility.value.set(key, false)
// next turn omits tools; current turn must be re-sent or handled by caller
}
} Prevention
- Advertise tool support per provider in the registry so tools are never sent to incapable endpoints.
- Keep the toolsCompatibility map persisted per provider key to avoid repeat failures after reload.
- Test new OpenAI-compatible backends with a minimal tool call before enabling builtin tools.
When it happens
Trigger: Streaming a chat turn with builtin tools against a provider/endpoint that does not implement the tools API — the provider returns a 400/422 naming 'tools', 'tool_choice', or function-calling; the wrapper downgrades and future calls for that key send no tools.
Common situations: OpenAI-compatible servers (llama.cpp, vLLM, LM Studio, Ollama builds) with partial or absent function-calling support; a proxy stripping tool fields then erroring; older model versions without tool support; wrong baseURL pointing at a chat-completions-only shim.
Related errors
- [llm] Auto-disabling content-part arrays for "${key}" and re
- [llm-streaming-control] signal handler failed
- [llm-streaming-control] handler failed
- [parseActEmotion] Failed to parse ACT payload JSON: "${paylo
AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18).
Data as JSON: /api/errors/fd27b3affaf734e4.
Report an issue: GitHub.