siyuan-note/siyuan · warning

capability execution was cancelled before it started

Error message

capability execution was cancelled before it started

What it means

validateCapabilityCall checks ctx.Err() before executing and rejects the call when the context is already cancelled or its deadline exceeded. This prevents starting capability work (LLM tool execution, possibly writes) after the request was aborted or timed out.

Solutions

  1. Check upstream context creation; raise deadlines if tool calls legitimately need longer
  2. Ignore/log this result when the caller itself initiated cancellation (it is expected, not a bug)
  3. In the agent loop, stop scheduling further rounds once ctx.Err() != nil
  4. Verify the client (UI or HTTP caller) is not aborting requests prematurely

Example fix

// before: one global short deadline for the whole agent run
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
// after: budget enough time for tool execution
ctx, cancel := context.WithTimeout(ctx, 2*time.Minute)
Defensive patterns

Strategy: validation

Validate before calling

if ctx.Err() != nil {
    return executedToolResult{Text: "cancelled", IsError: true}
}

Try / catch

select {
case <-ctx.Done():
    return executedToolResult{Text: "capability execution was cancelled before it started", IsError: true}
default:
    // proceed
}

Prevention

When it happens

Trigger: The HTTP request driving the agent round was cancelled by the client, the per-round context deadline expired before the tool call was validated, or the user hit stop/cancel in the UI while the model was streaming a tool call.

Common situations: User cancels a long AI chat, browser tab closes mid-request, gateway/proxy timeout kills the request, or deadline set too aggressively for slow tool calls.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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

Appendix: source

Thrown at kernel/agent/tools.go:64

	}
	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 执行单次工具调用。
func executeTool(ctx context.Context, tc openai.ToolCall, sessionID string) executedToolResult {
	tool, validator := tools.LookupToolWithValidator(tc.Function.Name)
	if tool == nil {

View on GitHub (pinned to 9f775e8a12)