{"record":{"id":"9f439d12b5af2b1f","repo":"siyuan-note/siyuan","slug":"unknown-tool-s","errorCode":null,"errorMessage":"unknown tool: %s","messagePattern":"unknown tool: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/agent/tools.go","lineNumber":42,"sourceCode":"\t\"strings\"\n\n\t\"github.com/sashabaranov/go-openai\"\n\t\"github.com/siyuan-note/siyuan/kernel/mcp/tools\"\n\tkernelModel \"github.com/siyuan-note/siyuan/kernel/model\"\n)\n\ntype executedToolResult struct {\n\tText             string\n\tModelAttachments []tools.ModelAttachment\n\tIsError          bool\n\tExecutionUnknown bool\n}\n\n// validateToolCallInput 在确认和快照之前校验工具调用，避免无效调用被误判为写操作。\nfunc validateToolCallInput(ctx context.Context, toolName string, args map[string]any) (*tools.Tool, *tools.ToolValidator, error) {\n\tt, validator := tools.LookupToolWithValidator(toolName)\n\tif t == nil {\n\t\treturn nil, nil, fmt.Errorf(\"unknown tool: %s\", toolName)\n\t}\n\tif t.ContextHandler == nil && t.Handler == nil {\n\t\treturn nil, nil, fmt.Errorf(\"tool handler unavailable: %s\", toolName)\n\t}\n\tif ctx.Err() != nil {\n\t\treturn nil, nil, fmt.Errorf(\"tool execution was cancelled before it started\")\n\t}\n\tif err := validator.ValidateInputContext(ctx, args); err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"invalid tool arguments: %w\", err)\n\t}\n\treturn t, validator, nil\n}\n\nfunc validateCapabilityCall(ctx context.Context, registration *capabilityRegistration, args map[string]any) error {\n\tif registration == nil {\n\t\treturn fmt.Errorf(\"capability was not exposed in this model round\")\n\t}\n\tif !capabilityStillExecutable(registration, args) {","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/agent/tools.go#L24-L60","documentation":"validateToolCallInput rejects a tool call whose toolName does not exist in the registered tool registry. tools.LookupToolWithValidator returns nil for any name that was never registered, so the agent cannot resolve a handler or validator and fails fast before treating the call as a write operation. This guards the confirmation/snapshot pipeline from invoking nonexistent tools.","triggerScenarios":"Calling validateToolCallInput (directly in tests like TestValidateToolCallInputRejectsMissingActionBeforeConfirmation, or via executeTool processing an LLM tool_call) with a toolName string that is not present in the tools registry — e.g. a typo, a renamed tool, or a model hallucinating a tool name.","commonSituations":"The model emits a tool name from an older tool schema after the registry was renamed; a test passes a fictional tool name; plugin/capability code registers tools under different identifiers than the ones the model was told about.","solutions":["Check the exact tool name against the registered tool list returned by the tools registry; fix the spelling or use the current registered name.","If the tool was renamed, update prompts/model schemas so the model only sees current tool names.","Ensure the tool is actually registered before tool calls are dispatched (registration ordering at agent startup)."],"exampleFix":"// before\nvalidateToolCallInput(ctx, \"file_writ\", args)\n// after\nvalidateToolCallInput(ctx, \"writeFile\", args) // exact registered tool name","handlingStrategy":"validation","validationCode":"if _, ok := registeredTools[toolName]; !ok {\n    return fmt.Errorf(\"tool %q is not registered\", toolName)\n}","typeGuard":null,"tryCatchPattern":"if _, _, err := validateToolCallInput(ctx, name, args); err != nil {\n    if strings.HasPrefix(err.Error(), \"unknown tool:\") { /* re-prompt model with valid tool list */ }\n}","preventionTips":["Generate the model's tool list from the same registry used at dispatch time","Keep tool names in a shared constant/package to avoid typos","Log unknown tool names to catch model hallucinations early"],"tags":["tool-registry","validation","agent"],"backgroundTag":"resource-not-found","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}