siyuan-note/siyuan · error
unknown tool
Error message
unknown tool: %s
What it means
validateToolCallInput looks up the requested tool by name with tools.LookupToolWithValidator. If no registered tool matches the name, it returns this error, so unrecognized tool names are rejected before confirmation and snapshot stages.
Solutions
- Check the exact registered tool names exposed to the model and correct the caller/model prompt
- Ensure the tool's registration function runs before the chat session starts
- Log the available tool list when this error occurs to spot typos or case mismatches
- If the model hallucinates names, tighten the tool schema/prompt describing available tools
Example fix
// before: assuming the tool exists
validateToolCallInput(ctx, "file_serach", args)
// after: verify against the registry first
if _, ok := tools.Lookup("file_search"); !ok {
return fmt.Errorf("tool %q is not registered", "file_search")
}
validateToolCallInput(ctx, "file_search", args) Defensive patterns
Strategy: validation
Validate before calling
if t, _ := tools.LookupToolWithValidator(toolName); t == nil {
return fmt.Errorf("tool %q not registered; available: %v", toolName, tools.Names())
} Try / catch
if _, _, err := validateToolCallInput(ctx, name, args); err != nil && strings.HasPrefix(err.Error(), "unknown tool:") {
return fmt.Errorf("model requested unregistered tool %q; check registry and prompt", name)
} Prevention
- Register all tools before starting a chat session
- Keep the model's tool schema list in sync with the registry
- Normalize tool name casing at the boundary
When it happens
Trigger: Calling validateToolCallInput (via the agent chat/tool-call path) with a toolName that is not registered in the tools registry: typo, model hallucinating a tool name, or a tool removed/renamed in a newer version.
Common situations: LLM emits a tool call with a name from an old or imagined schema; plugin/tool not registered because its registration code did not run; case mismatch in tool name.
Related errors
- invalid tool arguments
- capability was not exposed in this model round
- frontend capability description is required
- image MIME type is missing
- invalid agent runtime revision
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/9f439d12b5af2b1f.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/agent/tools.go:42
"strings"
"github.com/sashabaranov/go-openai"
"github.com/siyuan-note/siyuan/kernel/mcp/tools"
kernelModel "github.com/siyuan-note/siyuan/kernel/model"
)
type executedToolResult struct {
Text string
ModelAttachments []tools.ModelAttachment
IsError bool
ExecutionUnknown bool
}
// validateToolCallInput 在确认和快照之前校验工具调用,避免无效调用被误判为写操作。
func validateToolCallInput(ctx context.Context, toolName string, args map[string]any) (*tools.Tool, *tools.ToolValidator, error) {
t, validator := tools.LookupToolWithValidator(toolName)
if t == nil {
return nil, nil, fmt.Errorf("unknown tool: %s", toolName)
}
if t.ContextHandler == nil && t.Handler == nil {
return nil, nil, fmt.Errorf("tool handler unavailable: %s", toolName)
}
if ctx.Err() != nil {
return nil, nil, fmt.Errorf("tool execution was cancelled before it started")
}
if err := validator.ValidateInputContext(ctx, args); err != nil {
return nil, nil, fmt.Errorf("invalid tool arguments: %w", err)
}
return t, validator, nil
}
func validateCapabilityCall(ctx context.Context, registration *capabilityRegistration, args map[string]any) error {
if registration == nil {
return fmt.Errorf("capability was not exposed in this model round")
}
if !capabilityStillExecutable(registration, args) {View on GitHub (pinned to 9f775e8a12)