vxcontrol/pentagi · error
failed to perform agent chain for subtask %d: %w
Error message
failed to perform agent chain for subtask %d: %w
What it means
Run executes the LLM agent chain via Provider.PerformAgentChain. On any error from that call, the subtask is reset to Waiting, chain consistency is re-attempted (joined via errors.Join on failure), and the combined error is wrapped as 'failed to perform agent chain for subtask %d'. This is the top-level wrapper for all LLM/tool failures during subtask execution.
Source
Thrown at backend/pkg/controller/subtask.go:329
msgChainID = stw.subtaskCtx.MsgChainID
)
if err := stw.subtaskCtx.Provider.EnsureChainConsistency(ctx, msgChainID); err != nil {
stw.handleInterrupting(err)
return fmt.Errorf("failed to ensure chain consistency for subtask %d: %w", subtaskID, err)
}
performResult, err := stw.subtaskCtx.Provider.PerformAgentChain(ctx, taskID, subtaskID, msgChainID)
if err != nil {
if errors.Is(err, context.Canceled) {
ctx = context.Background()
}
errChainConsistency := stw.subtaskCtx.Provider.EnsureChainConsistency(ctx, msgChainID)
if errChainConsistency != nil {
err = errors.Join(err, errChainConsistency)
}
_ = stw.SetStatus(ctx, database.SubtaskStatusWaiting)
return fmt.Errorf("failed to perform agent chain for subtask %d: %w", subtaskID, err)
}
switch performResult {
case providers.PerformResultWaiting:
if err := stw.SetStatus(ctx, database.SubtaskStatusWaiting); err != nil {
stw.handleInterrupting(err)
return err
}
case providers.PerformResultDone:
if err := stw.SetStatus(ctx, database.SubtaskStatusFinished); err != nil {
stw.handleInterrupting(err)
return fmt.Errorf("failed to set subtask %d status to finished: %w", subtaskID, err)
}
case providers.PerformResultError:
if err := stw.SetStatus(ctx, database.SubtaskStatusFailed); err != nil {
stw.handleInterrupting(err)
return fmt.Errorf("failed to set subtask %d status to failed: %w", subtaskID, err)
}View on GitHub (pinned to ea665308ba)
Solutions
- Unwrap with errors.Is/errors.As: context.Canceled means the user/flow interrupted — no fix needed, subtask is already Waiting for resume; retry Run/PutInput later.
- For provider auth/quota errors, fix the API key or quota in Settings/env, then re-run the subtask (it stays Waiting).
- For network errors, verify egress connectivity/proxy settings to the LLM endpoint and retry.
- If errChainConsistency is joined in, reset the subtask's msgchain rows or recreate the subtask — the chain is too corrupted to resume.
- Check the specific LLM provider logs and tool container logs for the root cause before retrying.
Example fix
// before
if err := worker.Run(ctx); err != nil {
return err
}
// after
if err := worker.Run(ctx); err != nil {
switch {
case errors.Is(err, context.Canceled):
return nil // interrupted; subtask already reset to Waiting
case errors.Is(err, context.DeadlineExceeded):
return fmt.Errorf("chain timed out; retry with larger budget: %w", err)
default:
return err
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight: live context and configured provider before running
if err := ctx.Err(); err != nil {
return err
}
if apiKey == "" {
return fmt.Errorf("LLM provider API key not configured")
} Type guard
func classifyChainErr(err error) string {
switch {
case errors.Is(err, context.Canceled):
return "interrupted"
case errors.Is(err, context.DeadlineExceeded):
return "timeout"
case strings.Contains(err.Error(), "401"), strings.Contains(err.Error(), "quota"):
return "provider-auth"
default:
return "transient"
}
} Try / catch
if err := worker.Run(ctx); err != nil {
if strings.Contains(err.Error(), "failed to perform agent chain") {
switch classifyChainErr(err) {
case "interrupted":
return nil // subtask reset to Waiting; resume later
case "provider-auth":
return fmt.Errorf("fix provider key/quota then re-run: %w", err)
case "transient":
// subtask is Waiting again; retry Run after backoff
}
}
return err
} Prevention
- Validate provider API keys/quotas before starting a flow.
- Set realistic LLM timeouts and keep contexts alive for long chains.
- Monitor egress/proxy connectivity to the LLM endpoint from the backend container.
- Inspect joined errors (errors.Join) — a chain-consistency failure may be bundled and need chain reset.
- On repeated failures, recreate the subtask instead of infinite retry.
When it happens
Trigger: PerformAgentChain fails due to: LLM provider API error (invalid key, rate limit, timeout, context cancelled by flow interrupt), tool execution failure inside the Docker sandbox, DB failure while persisting chain messages, or EnsureChainConsistency failing during the post-error cleanup.
Common situations: Expired or quota-exhausted LLM API key; network egress blocked from the backend container to the LLM provider; user interrupted the flow cancelling ctx; tool container crashed mid-execution leaving the provider unable to complete the chain.
Related errors
- failed to switch provider: %w
- failed to put input for subtask %d: %w
- failed to set provider: %w
- failed to bulk-update flows provider name: %w
- failed to bulk-update assistants provider name: %w
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/b3a5b0844d9357a4.
Report an issue: GitHub.