{"record":{"id":"ff5f057428a4ae12","repo":"siyuan-note/siyuan","slug":"capability-handler-unavailable-s","errorCode":null,"errorMessage":"capability handler unavailable: %s","messagePattern":"capability handler unavailable: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/agent/tools.go","lineNumber":74,"sourceCode":"func 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) {\n\t\treturn fmt.Errorf(\"capability is disabled or no longer available: %s\", registration.ID)\n\t}\n\tif ctx.Err() != nil {\n\t\treturn fmt.Errorf(\"capability execution was cancelled before it started\")\n\t}\n\tif registration.Validator == nil {\n\t\treturn fmt.Errorf(\"capability validator unavailable: %s\", registration.ID)\n\t}\n\tif err := registration.Validator.ValidateInputContext(ctx, args); err != nil {\n\t\treturn fmt.Errorf(\"invalid capability arguments: %w\", err)\n\t}\n\tif !registration.isBrowser() &&\n\t\t(registration.Tool == nil || registration.Tool.ContextHandler == nil && registration.Tool.Handler == nil) {\n\t\treturn fmt.Errorf(\"capability handler unavailable: %s\", registration.ID)\n\t}\n\treturn nil\n}\n\n// executeTool 执行单次工具调用。\nfunc executeTool(ctx context.Context, tc openai.ToolCall, sessionID string) executedToolResult {\n\ttool, validator := tools.LookupToolWithValidator(tc.Function.Name)\n\tif tool == nil {\n\t\treturn executedToolResult{Text: \"unknown tool: \" + tc.Function.Name, IsError: true}\n\t}\n\treturn executeCapability(ctx, tc, sessionID, &capabilityRegistration{\n\t\tID:        tools.CapabilityIDForTool(tool),\n\t\tModelName: tool.Name,\n\t\tSource:    tool.Source,\n\t\tRuntime:   tool.Runtime,\n\t\tTool:      tool,\n\t\tValidator: validator,\n\t})","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/agent/tools.go#L56-L92","documentation":"After argument validation, validateCapabilityCall requires the registration to have an executable handler: for non-browser capabilities, registration.Tool must exist and expose ContextHandler or Handler. Otherwise the capability is declared but nothing can run it, so execution is refused.","triggerScenarios":"A capabilityRegistration carries a nil Tool, or a Tool whose Handler and ContextHandler are both nil (e.g. an MCP tool whose backend disconnected, or a tool registered as metadata-only) while isBrowser() is false.","commonSituations":"MCP server connection dropped leaving registered-but-unexecutable tool stubs, plugin tools failing to register their handler function, refactoring that splits registration from handler wiring.","solutions":["Reconnect the MCP server or reload the plugin so the tool regains its handler","Ensure tool registration populates Handler or ContextHandler before exposure","Skip exposing tools with nil handlers when building the round's capability list","Fix the registration path that admitted a handler-less tool"],"exampleFix":"// before: exposing every discovered tool\nfor _, t := range discovered { register(t) }\n// after: only expose tools with an executable handler\nfor _, t := range discovered {\n    if t.Handler != nil || t.ContextHandler != nil {\n        register(t)\n    }\n}","handlingStrategy":"validation","validationCode":"if !reg.isBrowser() && (reg.Tool == nil || (reg.Tool.ContextHandler == nil && reg.Tool.Handler == nil)) {\n    return executedToolResult{Text: \"capability handler unavailable: \" + reg.ID, IsError: true}\n}","typeGuard":"func executable(r *capabilityRegistration) bool {\n    return r.isBrowser() || (r.Tool != nil && (r.Tool.ContextHandler != nil || r.Tool.Handler != nil))\n}","tryCatchPattern":null,"preventionTips":["Never expose tools without Handler or ContextHandler","Recheck handler presence after MCP reconnects","Fail fast at registration time, not execution time"],"tags":["ai","tool-calling","internal","lifecycle"],"backgroundTag":"method-not-implemented","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}