siyuan-note/siyuan · error

capability was not exposed in this model round

Error message

capability was not exposed in this model round

What it means

validateCapabilityCall rejects a tool/capability invocation whose registration pointer is nil. Registration is created per model round when capabilities are exposed to the LLM; a nil registration means the model emitted a tool call for a capability that was never offered in the current round. executeCapability surfaces the message as an IsError tool result.

Solutions

  1. Ensure every executeCapability call site builds a non-nil capabilityRegistration (executeTool always does; check other paths)
  2. Re-send the current capability list to the model so its next tool call references an exposed capability
  3. Catch the IsError tool result in the agent loop and feed it back to the model as a corrective message
  4. Check MCP/plugin tool registration logs to see why the capability was not exposed this round

Example fix

// before: calling with a possibly-nil registration
executeCapability(ctx, tc, sessionID, lookupRegistration(name))
// after: guard before invoking
reg := lookupRegistration(name)
if reg == nil {
    return executedToolResult{Text: "unknown capability: " + name, IsError: true}
}
executeCapability(ctx, tc, sessionID, reg)
Defensive patterns

Strategy: validation

Validate before calling

reg := lookupRegistration(toolName)
if reg == nil {
    return executedToolResult{Text: "unknown capability: " + toolName, IsError: true}
}

Type guard

func registrationExposed(r *capabilityRegistration) bool { return r != nil }

Try / catch

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

Prevention

When it happens

Trigger: The model hallucinates a tool name or replays a tool call from a previous round after the capability list was narrowed, and executeCapability is invoked with registration == nil (e.g. an MCP/plugin capability that was de-registered between rounds).

Common situations: Agentic loops where the tool list changes mid-conversation (user disables an MCP server mid-session), models with weak tool-calling discipline replaying stale calls, or replayed/persisted conversations resumed against a changed capability set.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at kernel/agent/tools.go:58

	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) {
		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

View on GitHub (pinned to 9f775e8a12)