siyuan-note/siyuan · warning
tool execution was cancelled before it started
Error message
tool execution was cancelled before it started
What it means
Before validating arguments, validateToolCallInput checks ctx.Err() and aborts if the context is already cancelled or its deadline has expired. The tool call never starts; the error communicates that cancellation happened upstream so callers do not misattribute the failure to the tool itself.
Source
Thrown at kernel/agent/tools.go:48
type executedToolResult struct {
Text string
ModelAttachments []tools.ModelAttachment
IsError bool
ExecutionUnknown bool
}
// validateToolCallInput 在确认和快照之前校验工具调用,避免无效调用被误判为写操作。
func validateToolCallInput(ctx context.Context, toolName string, args map[string]any) (*tools.Tool, *tools.ToolValidator, error) {
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 {View on GitHub (pinned to 8641553a1f)
Solutions
- Check why the context was cancelled: inspect upstream timeout/deadline settings and increase them if the budget is too small.
- Skip re-dispatching the tool call after cancellation; treat it as an intentional abort and let the agent round end.
- Ensure contexts are only cancelled after in-flight tool calls are drained during shutdown.
Example fix
// before
result, err := runAgentRound(ctx) // ctx already cancelled
// after
if ctx.Err() != nil {
ctx = context.Background() // or create a fresh deadline-scoped ctx before the round
}
result, err := runAgentRound(ctx) Defensive patterns
Strategy: try-catch
Validate before calling
if ctx.Err() != nil {
return nil, fmt.Errorf("cannot dispatch tool: %w", ctx.Err())
} Try / catch
if _, _, err := validateToolCallInput(ctx, name, args); err != nil {
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) { /* abort round gracefully */ }
} Prevention
- Set realistic per-round deadlines before dispatching tool calls
- Drain queued tool calls before cancelling contexts on shutdown
- Create a fresh context per model round instead of reusing long-lived ones
When it happens
Trigger: Executing a tool call with a context that was cancelled (ctx.CancelFunc called) or whose deadline timed out before validateToolCallInput ran — e.g. the HTTP request shut down, the session ended, or a parent deadline expired while the call was queued.
Common situations: Client disconnects mid agent run; a model round's overall timeout elapses before the tool dispatch; shutdown path cancels worker contexts while queued tool calls are processed.
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
- capability execution was cancelled before it started
- image generation was cancelled
- read body failed: %s
- model request timeout
- model stream idle timeout
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/2b642bb4de211834.
Report an issue: GitHub.