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
- Ensure every executeCapability call site builds a non-nil capabilityRegistration (executeTool always does; check other paths)
- Re-send the current capability list to the model so its next tool call references an exposed capability
- Catch the IsError tool result in the agent loop and feed it back to the model as a corrective message
- 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
- Always build registrations via executeTool, which guarantees non-nil
- Re-sync the exposed capability list each model round
- Feed validation errors back to the model as corrective tool results
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
- capability is disabled or no longer available
- capability validator unavailable
- invalid capability arguments
- tool arguments must be a JSON object
- AI editor action must not be empty
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 nilView on GitHub (pinned to 9f775e8a12)