{"record":{"id":"cc73d511131ae4da","repo":"vxcontrol/pentagi","slug":"failed-to-renew-flow-d-status-w","errorCode":null,"errorMessage":"failed to renew flow %d status: %w","messagePattern":"failed to renew flow (.+?) status: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/controller/flows.go","lineNumber":262,"sourceCode":"\t\t})\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to create flow worker: %w\", err)\n\t\t}\n\n\t\tfc.flows[fw.GetFlowID()] = fw\n\t\tflowID = fw.GetFlowID()\n\t\tfw.SetStatus(ctx, database.FlowStatusWaiting)\n\n\t\treturn nil\n\t}\n\n\tloadFlow := func() error {\n\t\tflow, err := fc.db.UpdateFlowStatus(ctx, database.UpdateFlowStatusParams{\n\t\t\tID:     flowID,\n\t\t\tStatus: database.FlowStatusWaiting,\n\t\t})\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to renew flow %d status: %w\", flowID, err)\n\t\t}\n\n\t\tfw, err = LoadFlowWorker(ctx, flow, flowWorkerCtx)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to load flow %d: %w\", flowID, err)\n\t\t}\n\n\t\tfc.flows[flowID] = fw\n\n\t\treturn nil\n\t}\n\n\tif flowID == 0 {\n\t\tif err := newFlow(); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t} else if fw, ok = fc.flows[flowID]; ok {\n\t\tstatus, err := fw.GetStatus(ctx)","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/controller/flows.go#L244-L280","documentation":"Wrap inside the loadFlow closure of CreateAssistant. Before reloading a flow worker, the controller resets the flow's status to FlowStatusWaiting via db.UpdateFlowStatus; if that DB update fails the error is wrapped with the flow ID so callers know which flow could not be renewed.","triggerScenarios":"CreateAssistant with an existing flowID whose status is Finished/Failed (or which is not in the in-memory map), and the UpdateFlowStatus SQL call fails — DB down, connection pool exhausted, row for flowID deleted, context canceled/deadline exceeded.","commonSituations":"PostgreSQL restart or network blip mid-request, the flow row was removed while workers still reference it, migration drift leaving status enum values missing, or the request context timing out before the UPDATE completes.","solutions":["Check PostgreSQL availability and backend logs for the underlying driver error.","Verify the flow row with that ID still exists (it may have been deleted while in-memory state was stale).","Increase the request/database timeout; a canceled ctx aborts the UPDATE.","Run pending goose migrations so the flow status enum/columns match the code.","Retry CreateAssistant once the database is healthy."],"exampleFix":"// before\nflow row deleted externally -> UpdateFlowStatus returns 0 rows/error\n// after\nrecreate the flow (flowID=0) or restore the row; e.g.\nSELECT id FROM flows WHERE id = :flowID; -- confirm existence before reusing the ID","handlingStrategy":"retry","validationCode":"// verify the flow row still exists before reusing the ID\nvar n int\nerr := db.QueryRowContext(ctx, `SELECT count(*) FROM flows WHERE id = $1`, flowID).Scan(&n)\nif err != nil || n == 0 { return fmt.Errorf(\"flow %d no longer exists\", flowID) }","typeGuard":null,"tryCatchPattern":"if err := loadFlow(); err != nil {\n    if isTransientDBError(errors.Unwrap(err)) {\n        time.Sleep(backoff); retry once\n    }\n    return err\n}","preventionTips":["Use request contexts with generous timeouts for DB-backed operations.","Monitor PostgreSQL availability and pool saturation.","Never delete flow rows while the backend may still reference them.","Keep migrations in sync with the deployed binary."],"tags":["go","database","flow-status","wrapped-error"],"backgroundTag":"database-update-failed","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}