{"record":{"id":"a738ab98dad11aaf","repo":"vxcontrol/pentagi","slug":"failed-to-get-subtasks-w","errorCode":null,"errorMessage":"failed to get subtasks: %w","messagePattern":"failed to get subtasks: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/tools/flow_manager.go","lineNumber":221,"sourceCode":"\n\treturn taskList, nil\n}\n\nfunc (t *flowStatusTool) buildSubtasksList(ctx context.Context, taskID *int64, verbose bool) (string, error) {\n\tvar subtasks []database.Subtask\n\tvar err error\n\n\tif taskID != nil && *taskID > 0 {\n\t\tsubtasks, err = t.db.GetFlowTaskSubtasks(ctx, database.GetFlowTaskSubtasksParams{\n\t\t\tFlowID: t.flowID,\n\t\t\tTaskID: *taskID,\n\t\t})\n\t} else {\n\t\tsubtasks, err = t.db.GetFlowSubtasks(ctx, t.flowID)\n\t}\n\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to get subtasks: %w\", err)\n\t}\n\n\tif len(subtasks) == 0 {\n\t\treturn \"No subtasks found.\", nil\n\t}\n\n\tsb := &strings.Builder{}\n\tif taskID != nil && *taskID > 0 {\n\t\tfmt.Fprintf(sb, \"Subtasks for task %d:\\n\\n\", *taskID)\n\t} else {\n\t\tfmt.Fprintf(sb, \"All subtasks for flow %d:\\n\\n\", t.flowID)\n\t}\n\tfor _, st := range subtasks {\n\t\tfmt.Fprintf(sb, \"Subtask ID: %d | Task ID: %d | Status: %s | Title: %s\\n\",\n\t\t\tst.ID, st.TaskID, st.Status, st.Title)\n\t\tif verbose {\n\t\t\tif st.Description != \"\" {\n\t\t\t\tdescription, err := t.getDescriptionText(ctx, st.Description)","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/flow_manager.go#L203-L239","documentation":"Thrown in buildSubtasksList (backend/pkg/tools/flow_manager.go:221) when either GetFlowTaskSubtasks (filtered by task_id) or GetFlowSubtasks (whole flow) fails. It means get_flow_status with detail='subtasks' could not read the subtask rows; the wrapped cause carries the actual database error.","triggerScenarios":"get_flow_status with detail='subtasks' where the DB query fails — PostgreSQL unreachable, statement/context timeout, connection-pool exhaustion, or a schema mismatch (e.g. missing subtasks table after failed migration); also fires with a bad task_id only if the query itself errors, not when rows are empty.","commonSituations":"Database restart or failover during an agent session; DB credentials rotated in .env without backend restart... actually with restart needed; goose migration partially applied leaving schema drift; heavy concurrent load saturating pg connections.","solutions":["Confirm PostgreSQL health and connectivity (pg_isready, docker compose logs postgres); restart if degraded.","Unwrap the cause from logs and address it specifically (auth, timeout, undefined table).","Re-run goose migrations (backend/migrations/sql) if schema drift is detected and restart the backend.","Retry the tool call after DB recovery; tune pool/timeout settings if exhaustion was the cause."],"exampleFix":"// before\nif err != nil {\n\treturn \"\", fmt.Errorf(\"failed to get subtasks: %w\", err)\n}\n// after: add one retry for transient DB errors\nsubtasks, err = t.db.GetFlowSubtasks(ctx, t.flowID)\nif err != nil && isTransientDBError(err) {\n\ttime.Sleep(500 * time.Millisecond)\n\tsubtasks, err = t.db.GetFlowSubtasks(ctx, t.flowID)\n}\nif err != nil {\n\treturn \"\", fmt.Errorf(\"failed to get subtasks: %w\", err)\n}","handlingStrategy":"retry","validationCode":"// validate DB access and args before the tool call\nif err := db.PingContext(ctx); err != nil {\n\treturn fmt.Errorf(\"postgres unreachable: %w\", err)\n}\nif taskID != nil && *taskID <= 0 {\n\ttaskID = nil // fall back to flow-wide subtask query\n}","typeGuard":null,"tryCatchPattern":"// Go: bounded retry with DB-error classification\nvar out string\nerr := retry.OnError(ctx, 3, isTransientDBError, func() error {\n\tvar e error\n\tout, e = tool.Handle(ctx, \"get_flow_status\", subtasksArgs)\n\treturn e\n})\nif err != nil {\n\treturn fmt.Errorf(\"subtasks listing failed: %w\", err)\n}","preventionTips":["Health-check PostgreSQL in compose and before agent sessions.","Keep schema migrations (goose) synchronized with SQLC query versions.","Validate task_id arguments (positive, existing) before detail='subtasks' calls.","Tune connection pool for the number of concurrent flows."],"tags":["database","postgresql","tool","flow-status"],"backgroundTag":"database-query-failed","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}