siyuan-note/siyuan · error

capability handler unavailable: %s

Error message

capability handler unavailable: %s

What it means

The last validation in validateCapabilityCall (kernel/agent/tools.go:72-75): a non-browser capability must have a Tool whose ContextHandler or Handler is set. Browser capabilities (Runtime == "browser") are exempt because their handlers live in the frontend and calls are dispatched back over SSE. Failing this check means the registration points at a backend tool with no executable function — an internal registration bug, not a user input problem.

Source

Thrown at kernel/agent/tools.go:74

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) {
		return fmt.Errorf("capability is disabled or no longer available: %s", registration.ID)
	}
	if ctx.Err() != nil {
		return fmt.Errorf("capability execution was cancelled before it started")
	}
	if registration.Validator == nil {
		return fmt.Errorf("capability validator unavailable: %s", registration.ID)
	}
	if err := registration.Validator.ValidateInputContext(ctx, args); err != nil {
		return fmt.Errorf("invalid capability arguments: %w", err)
	}
	if !registration.isBrowser() &&
		(registration.Tool == nil || registration.Tool.ContextHandler == nil && registration.Tool.Handler == nil) {
		return fmt.Errorf("capability handler unavailable: %s", registration.ID)
	}
	return nil
}

// executeTool 执行单次工具调用。
func executeTool(ctx context.Context, tc openai.ToolCall, sessionID string) executedToolResult {
	tool, validator := tools.LookupToolWithValidator(tc.Function.Name)
	if tool == nil {
		return executedToolResult{Text: "unknown tool: " + tc.Function.Name, IsError: true}
	}
	return executeCapability(ctx, tc, sessionID, &capabilityRegistration{
		ID:        tools.CapabilityIDForTool(tool),
		ModelName: tool.Name,
		Source:    tool.Source,
		Runtime:   tool.Runtime,
		Tool:      tool,
		Validator: validator,
	})

View on GitHub (pinned to afa823b6b4)

Solutions

  1. Look up the capability ID in the message, find its registration, and set Tool.ContextHandler or Tool.Handler
  2. If the capability is frontend-hosted, ensure Runtime is exactly "browser" (isBrowser check, capability.go:109-111) so it takes the SSE dispatch path
  3. Assert in tests that every registered non-browser tool has a handler (pattern in kernel/agent/capability_test.go)
  4. If hit with unmodified stock tools, report the capability ID — it marks a packaging/version defect
Defensive patterns

Strategy: try-catch

Validate before calling

// Registration builders: require a handler for backend tools
if !reg.isBrowser() && (reg.Tool == nil || (reg.Tool.ContextHandler == nil && reg.Tool.Handler == nil)) {
    // refuse registration
}

Type guard

null

Try / catch

if err := validateCapabilityCall(ctx, reg, args); err != nil {
    if strings.Contains(err.Error(), "capability handler unavailable") {
        // internal defect: log capability ID and drop the registration
    }
}

Prevention

When it happens

Trigger: A backend capabilityRegistration built with Tool == nil or with a tools.Tool that defines neither Handler nor ContextHandler — e.g. a tool registered for its schema/effects only, a refactor removing a handler without pruning the registration, or a native tool declaration misclassified as non-browser. Browser-capability paths (handleBrowserCapability) never hit it.

Common situations: Kernel/plugin development: declaring a tool's schema for prompt-building but wiring no handler; copy-paste registrations; version skew where a tool struct lost its handler in a refactor.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18). Data as JSON: /api/errors/ff5f057428a4ae12. Report an issue: GitHub.