vxcontrol/pentagi · error
failed to ensure chain consistency for subtask %d: %w
Error message
failed to ensure chain consistency for subtask %d: %w
What it means
Before executing the agent chain, Run calls Provider.EnsureChainConsistency to repair/validate the LLM message chain (e.g. dangling tool calls after a crash). If that fails, the error is wrapped as 'failed to ensure chain consistency for subtask %d' and the subtask is reset to Waiting via handleInterrupting when the cause is a context interruption.
Source
Thrown at backend/pkg/controller/subtask.go:316
if stw.IsWaiting() {
return fmt.Errorf("subtask is waiting, put input first")
}
if err := stw.SetStatus(ctx, database.SubtaskStatusRunning); err != nil {
stw.handleInterrupting(err)
return err
}
var (
taskID = stw.subtaskCtx.TaskID
subtaskID = stw.subtaskCtx.SubtaskID
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 {View on GitHub (pinned to ea665308ba)
Solutions
- Read the wrapped error: for context.Canceled/DeadlineExceeded retry with a fresh context (handleInterrupting already reset the subtask to Waiting, so just call Run again).
- For corrupted chains, delete/reset the msgchain rows for this subtask (or recreate the subtask) so EnsureChainConsistency can rebuild cleanly.
- Verify DB health and migrations — chain repair reads and writes msgchain tables and fails on connectivity or missing tables.
- Check provider logs for which chain message was inconsistent; manually truncate trailing dangling tool calls if the automatic repair refuses.
Example fix
// before
if err := worker.Run(ctx); err != nil {
return err
}
// after
if err := worker.Run(ctx); err != nil {
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
resetCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
return worker.Run(resetCtx) // subtask was reset to Waiting by handleInterrupting
}
return err
} Defensive patterns
Strategy: retry
Validate before calling
// pre-check that the subtask is readable before resuming
if _, err := worker.GetStatus(ctx); err != nil {
return err // cannot even read subtask; DB issue
} Type guard
func isInterruptErr(err error) bool {
return errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded)
} Try / catch
if err := worker.Run(ctx); err != nil {
if strings.Contains(err.Error(), "failed to ensure chain consistency") {
if isInterruptErr(err) {
// subtask already reset to Waiting; retry with fresh ctx
resetCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
return worker.Run(resetCtx)
}
// corrupted chain: recreate the subtask/chain
}
return err
} Prevention
- Gracefully shut down workers (cancel + drain) so chains never end mid tool-call.
- Run migrations and keep the msgchain store healthy.
- On unrecoverable corruption, recreate the subtask rather than retrying Run forever.
- Retry interrupted runs with a fresh background context and timeout.
When it happens
Trigger: EnsureChainConsistency fails on DB errors while reading/repairing the chain rows, a cancelled/deadline-exceeded ctx, or a corrupted/incomplete chain (e.g. assistant message with a dangling tool_call after a previous crash) that the repair logic cannot fix.
Common situations: Previous Run crashed mid-chain (container killed, OOM, pod restart) leaving a broken chain; database outage at chain-repair time; flow data restored from backup with partially written msgchain rows.
Related errors
- failed to put input for subtask %d: %w
- failed to switch provider: %w
- failed to bulk-update flows provider name: %w
- failed to bulk-update assistants provider name: %w
- failed to perform agent chain for subtask %d: %w
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/9a0d2250042ffcc1.
Report an issue: GitHub.