{"record":{"id":"3561fe4cddee593a","repo":"vxcontrol/pentagi","slug":"failed-to-get-planned-subtasks-for-task-d-w","errorCode":null,"errorMessage":"failed to get planned subtasks for task %d: %w","messagePattern":"failed to get planned subtasks for task (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/tools/flow_manager.go","lineNumber":879,"sourceCode":"\t}\n\n\ttaskBelongsToFlow := false\n\tfor _, task := range tasks {\n\t\tif task.ID == action.TaskID {\n\t\t\ttaskBelongsToFlow = true\n\t\t\tbreak\n\t\t}\n\t}\n\tif !taskBelongsToFlow {\n\t\treturn \"\", stateGuard(fmt.Errorf(\n\t\t\t\"task ID %d was not found in this flow; \"+\n\t\t\t\t\"obtain a valid task ID from %s with detail='tasks'\",\n\t\t\taction.TaskID, GetFlowStatusToolName))\n\t}\n\n\tplanned, err := t.db.GetTaskPlannedSubtasks(ctx, action.TaskID)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to get planned subtasks for task %d: %w\", action.TaskID, err)\n\t}\n\n\tif len(planned) == 0 && len(action.Operations) > 0 {\n\t\tsubtasks, err := t.db.GetFlowSubtasks(ctx, t.flowID)\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"failed to check subtask state for task %d: %w\", action.TaskID, err)\n\t\t}\n\n\t\tfor _, st := range subtasks {\n\t\t\tif st.TaskID != action.TaskID {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tswitch st.Status {\n\t\t\tcase database.SubtaskStatusWaiting:\n\t\t\t\treturn \"\", stateGuard(fmt.Errorf(\n\t\t\t\t\t\"task %d has a subtask (ID: %d, %q) waiting for user input. \"+\n\t\t\t\t\t\t\"Only 'created' subtasks can be patched, but you can include the waiting subtask's ID in your operations to modify or remove it. \"+\n\t\t\t\t\t\t\"Alternatively, answer it via %s first\",","sourceCodeStart":861,"sourceCodeEnd":897,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/flow_manager.go#L861-L897","documentation":"This error wraps a database failure from GetTaskPlannedSubtasks while the flow tool Handle is processing a create-subtasks/patch-subtasks action. It means the backend could not read the planned subtasks for the given task ID from PostgreSQL; the underlying DB error is preserved via %w. It is thrown before any subtask state checks can run.","triggerScenarios":"Any call to the create_subtasks (or patch) tool action where t.db.GetTaskPlannedSubtasks(ctx, action.TaskID) returns a non-nil error — e.g. DB connection dropped, query timeout, or the task row lock is unavailable.","commonSituations":"PostgreSQL outage or connection pool exhaustion under load; context deadline exceeded because the agent's request timed out; transient network blip between the backend and the database; corrupted schema after a failed migration.","solutions":["Inspect the wrapped cause (%w) in the logs to identify the underlying DB error","Check PostgreSQL connectivity/health and connection-pool settings","Retry the tool action; transient DB failures usually resolve on reconnect","If persistent, verify migrations ran and the tasks/subtasks tables exist"],"exampleFix":"// before\nplanned, err := t.db.GetTaskPlannedSubtasks(ctx, action.TaskID)\nif err != nil {\n\treturn \"\", fmt.Errorf(\"failed to get planned subtasks for task %d: %w\", action.TaskID, err)\n}\n// after\nplanned, err := t.db.GetTaskPlannedSubtasks(ctx, action.TaskID)\nif err != nil {\n\tlogger.Warn(ctx, \"retrying planned-subtask fetch\", slog.Int(\"task_id\", action.TaskID), slog.String(\"err\", err.Error()))\n\tplanned, err = t.db.GetTaskPlannedSubtasks(ctx, action.TaskID)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to get planned subtasks for task %d: %w\", action.TaskID, err)\n\t}\n}","handlingStrategy":"retry","validationCode":"// caller-side preflight\nif taskID <= 0 {\n\treturn fmt.Errorf(\"invalid task ID %d\", taskID)\n}\nif err := ctx.Err(); err != nil {\n\treturn fmt.Errorf(\"context already cancelled: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"// in Go, inspect the wrapped error\nplanned, err := mgr.Handle(ctx, action)\nif err != nil {\n\tvar dbErr *pgconn.ConnectError\n\tif errors.As(err, &dbErr) || errors.Is(err, context.DeadlineExceeded) {\n\t\t// transient: retry with backoff\n\t}\n\treturn fmt.Errorf(\"get planned subtasks: %w\", err)\n}","preventionTips":["Always check the wrapped (%w) cause to distinguish transient DB errors from permanent ones","Use retries with backoff for transient DB failures","Monitor PostgreSQL connection-pool saturation and health","Keep migrations up to date before starting flows"],"tags":["database","flow-manager","db-query"],"backgroundTag":"database-query-failed","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}