vxcontrol/pentagi · error
failed to check subtask state for task
Error message
failed to check subtask state for task %d: %w
What it means
This error wraps a failure of t.db.GetFlowSubtasks for the flow while Handle was checking whether any existing subtasks belong to the task, because no planned subtasks were found but the action carried operations. It is a defensive consistency check: the agent wants to patch/create subtasks but the DB state could not be verified. The wrapped cause carries the real DB error.
Solutions
- Check the wrapped DB error in logs to find the root cause
- Verify PostgreSQL is reachable and the connection pool is not exhausted
- Retry the action once connectivity is restored
- Ensure goose migrations completed so the subtasks table is queryable
Example fix
// before
subtasks, err := t.db.GetFlowSubtasks(ctx, t.flowID)
if err != nil {
return "", fmt.Errorf("failed to check subtask state for task %d: %w", action.TaskID, err)
}
// after
subtasks, err := t.db.GetFlowSubtasks(ctx, t.flowID)
if err != nil {
if ctx.Err() != nil {
return "", fmt.Errorf("flow context cancelled while checking subtask state for task %d: %w", action.TaskID, ctx.Err())
}
return "", fmt.Errorf("failed to check subtask state for task %d: %w", action.TaskID, err)
} Defensive patterns
Strategy: retry
Validate before calling
// preflight: ensure flow context and DB are alive before invoking the tool
if err := db.PingContext(ctx); err != nil {
return fmt.Errorf("database unreachable: %w", err)
} Try / catch
subtasks, err := mgr.Handle(ctx, action)
if err != nil && strings.Contains(err.Error(), "failed to check subtask state") {
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
// re-invoke with a fresh context
}
} Prevention
- Avoid invoking plan-mutation tools with a nearly expired context/deadline
- Ensure the subtasks table exists (migrations ran) before running flows
- Retry transient DB errors instead of abandoning the flow action
- Watch DB connection-pool metrics during large flows
When it happens
Trigger: Create/patch-subtasks action with len(action.Operations) > 0 and zero planned subtasks, and GetFlowSubtasks(ctx, t.flowID) returns a DB error (connection failure, timeout, cancelled context).
Common situations: Database under heavy load during large flows; ctx cancelled by an upstream deadline; replica/failover hiccup in PostgreSQL; misconfigured DSN after an environment change.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- failed to get planned subtasks for task
- database status update failed during container stop
- error checking token status
- error checking user status
- failed to bulk-update assistants provider name
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/054c6620a7bb9783.
Report an issue: GitHub.
Appendix: source
Thrown at backend/pkg/tools/flow_manager.go:885
break
}
}
if !taskBelongsToFlow {
return "", stateGuard(fmt.Errorf(
"task ID %d was not found in this flow; "+
"obtain a valid task ID from %s with detail='tasks'",
action.TaskID, GetFlowStatusToolName))
}
planned, err := t.db.GetTaskPlannedSubtasks(ctx, action.TaskID)
if err != nil {
return "", fmt.Errorf("failed to get planned subtasks for task %d: %w", action.TaskID, err)
}
if len(planned) == 0 && len(action.Operations) > 0 {
subtasks, err := t.db.GetFlowSubtasks(ctx, t.flowID)
if err != nil {
return "", fmt.Errorf("failed to check subtask state for task %d: %w", action.TaskID, err)
}
for _, st := range subtasks {
if st.TaskID != action.TaskID {
continue
}
switch st.Status {
case database.SubtaskStatusWaiting:
return "", stateGuard(fmt.Errorf(
"task %d has a subtask (ID: %d, %q) waiting for user input. "+
"Only 'created' subtasks can be patched, but you can include the waiting subtask's ID in your operations to modify or remove it. "+
"Alternatively, answer it via %s first",
action.TaskID, st.ID, st.Title, SubmitFlowInputToolName))
case database.SubtaskStatusRunning:
return "", stateGuard(fmt.Errorf(
"task %d has a subtask (ID: %d, %q) currently running. "+
"Call %s first, then retry",
action.TaskID, st.ID, st.Title, StopFlowToolName))View on GitHub (pinned to ea665308ba)