siyuan-note/siyuan · error

capability is disabled or no longer available

Error message

capability is disabled or no longer available: %s

What it means

validateCapabilityCall calls capabilityStillExecutable(registration, args) and rejects the invocation when it returns false. The capability is registered but has been disabled (e.g. toggled off in settings) or removed since exposure. The registration ID is embedded in the message for diagnosis.

Solutions

  1. Re-enable the MCP server / plugin tool that provides the capability ID shown in the message
  2. Verify tool availability before starting the agent round so stale tools are not exposed
  3. Handle the IsError result in the agent loop and inform the model the tool is gone
  4. Check capabilityStillExecutable to confirm which sub-condition failed for this registration

Example fix

// before: exposing tools without availability check
for _, t := range cachedTools {
    expose(t)
}
// after: only expose currently available tools
for _, t := range cachedTools {
    if toolStillAvailable(t) {
        expose(t)
    }
}
Defensive patterns

Strategy: validation

Validate before calling

if !capabilityStillExecutable(reg, args) {
    return executedToolResult{Text: "capability unavailable: " + reg.ID, IsError: true}
}

Try / catch

if err := validateCapabilityCall(ctx, reg, args); err != nil {
    return executedToolResult{Text: err.Error(), IsError: true}
}

Prevention

When it happens

Trigger: A tool exposed to the model at round start becomes disabled before its call executes: user disables the MCP server or plugin tool, a snapshot/confirm flow invalidates the registration, or capabilityStillExecutable's own checks (re-lookup of the tool, argument-dependent gating) fail.

Common situations: User disables a plugin mid-agent-run, MCP server reconnect fails leaving tools unavailable, or long-running agent sessions where the tool set changes between exposure and execution.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/19f304909958a169. Report an issue: GitHub.

Appendix: source

Thrown at kernel/agent/tools.go:61

	}
	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) {
		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 执行单次工具调用。

View on GitHub (pinned to 9f775e8a12)