{"record":{"id":"7c5b25a2edfef79d","repo":"vxcontrol/pentagi","slug":"failed-to-set-flow-d-status-w","errorCode":null,"errorMessage":"failed to set flow %d status: %w","messagePattern":"failed to set flow (.+?) status: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/controller/flow.go","lineNumber":547,"sourceCode":"func (fw *flowWorker) GetStatus(ctx context.Context) (database.FlowStatus, error) {\n\tflow, err := fw.flowCtx.DB.GetUserFlow(ctx, database.GetUserFlowParams{\n\t\tUserID: fw.flowCtx.UserID,\n\t\tID:     fw.flowCtx.FlowID,\n\t})\n\tif err != nil {\n\t\treturn database.FlowStatusFailed, err\n\t}\n\n\treturn flow.Status, nil\n}\n\nfunc (fw *flowWorker) SetStatus(ctx context.Context, status database.FlowStatus) error {\n\tflow, err := fw.flowCtx.DB.UpdateFlowStatus(ctx, database.UpdateFlowStatusParams{\n\t\tStatus: status,\n\t\tID:     fw.flowCtx.FlowID,\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to set flow %d status: %w\", fw.flowCtx.FlowID, err)\n\t}\n\n\tcontainers, err := fw.flowCtx.DB.GetFlowContainers(ctx, fw.flowCtx.FlowID)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get flow %d containers: %w\", fw.flowCtx.FlowID, err)\n\t}\n\n\tfw.flowCtx.Publisher.FlowUpdated(ctx, flow, containers)\n\n\treturn nil\n}\n\n// InvalidateTaskSubtasks drops stale workers after direct DB deletion,\n// preventing delayed ErrNoRows failures.\nfunc (fw *flowWorker) InvalidateTaskSubtasks(ctx context.Context, taskID int64, subtaskIDs []int64) {\n\ttask, err := fw.tc.GetTask(ctx, taskID)\n\tif err != nil {\n\t\treturn","sourceCodeStart":529,"sourceCodeEnd":565,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/controller/flow.go#L529-L565","documentation":"flowWorker.SetStatus persists a new flow status via UpdateFlowStatus and then republishes the flow. If the UPDATE fails (DB error or cancelled context), the error is wrapped as 'failed to set flow %d status'. Callers (Finish, worker loop, processInput) rely on this to transition lifecycle state, so a failure here can leave a flow stuck in its previous status.","triggerScenarios":"UpdateFlowStatus returns an error: Postgres unreachable, context cancelled (e.g. worker shutting down or client-driven ctx), row lock contention, or the flow row was deleted concurrently.","commonSituations":"Graceful shutdown cancelling ctx mid-update; DB failover/connection pool exhaustion during heavy runs; flow soft-deleted by the user in the UI while its worker tries to set status; migration missing.","solutions":["Check the wrapped cause in logs: sql.ErrNoRows (flow deleted) vs driver/conn errors vs context.Canceled.","Retry the status update with context.WithoutCancel(ctx) during shutdown paths so the final status is persisted.","Confirm the flow still exists (not soft-deleted) if ErrNoRows.","Verify Postgres connectivity and pool limits if failures cluster under load.","Re-run migrations if the flows table/schema is missing columns."],"exampleFix":"// before\nerr := fw.SetStatus(ctx, database.FlowStatusFinished) // ctx cancelled at shutdown, status lost\n// after\nerr := fw.SetStatus(context.WithoutCancel(ctx), database.FlowStatusFinished)\nif err != nil {\n    log.WithError(err).Error(\"failed to persist final flow status\")\n}","handlingStrategy":"retry","validationCode":"if _, err := db.GetFlow(ctx, flowID); err != nil {\n    return fmt.Errorf(\"flow %d gone, cannot set status: %w\", flowID, err)\n}","typeGuard":null,"tryCatchPattern":"err := fw.SetStatus(ctx, database.FlowStatusFinished)\nif err != nil {\n    if errors.Is(err, context.Canceled) {\n        err = fw.SetStatus(context.WithoutCancel(ctx), database.FlowStatusFinished)\n    }\n    if err != nil { log.WithError(err).Error(\"flow status not persisted\") }\n}","preventionTips":["Use context.WithoutCancel for terminal status writes during shutdown","Retry transient DB errors with backoff","Check for soft-deleted flows when ErrNoRows is the cause","Alert on SetStatus failures — they leave flows in stale lifecycle states"],"tags":["go","database","state-machine","flow-status"],"backgroundTag":"database-update-failed","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}