{"record":{"id":"9261f35875ef6eb7","repo":"vxcontrol/pentagi","slug":"failed-to-get-flow-agent-log-w","errorCode":null,"errorMessage":"failed to get flow agent log: %w","messagePattern":"failed to get flow agent log: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/controller/flow.go","lineNumber":1220,"sourceCode":"\treturn &flowProviderWorkers{\n\t\tmlw:  mlw,\n\t\talw:  alw,\n\t\tslw:  slw,\n\t\ttlw:  tlw,\n\t\tvslw: vslw,\n\t\ttclw: tclw,\n\t\tsw:   sw,\n\t}, nil\n}\n\nfunc getFlowProviderWorkers(\n\tctx context.Context,\n\tflowID int64,\n\tcnts *flowProviderControllers,\n) (*flowProviderWorkers, error) {\n\talw, err := cnts.alc.GetFlowAgentLog(ctx, flowID)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get flow agent log: %w\", err)\n\t}\n\n\tmlw, err := cnts.mlc.GetFlowMsgLog(ctx, flowID)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get flow msg log: %w\", err)\n\t}\n\n\tslw, err := cnts.slc.GetFlowSearchLog(ctx, flowID)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get flow search log: %w\", err)\n\t}\n\n\ttlw, err := cnts.tlc.GetFlowTermLog(ctx, flowID)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get flow term log: %w\", err)\n\t}\n\n\tvslw, err := cnts.vslc.GetFlowVectorStoreLog(ctx, flowID)","sourceCodeStart":1202,"sourceCodeEnd":1238,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/controller/flow.go#L1202-L1238","documentation":"getFlowProviderWorkers rebuilds the worker set for an existing flow (e.g. on restart/resume); its first step fetches the agent log worker via cnts.alc.GetFlowAgentLog(ctx, flowID). Failure is wrapped with this message and flow resume aborts — the existing flow's agent-log worker could not be reattached.","triggerScenarios":"Resuming/restarting a flow calls getFlowProviderWorkers and GetFlowAgentLog fails — the agent log record for this flowID does not exist (never created or already cleaned up), DB unreachable, or context cancelled.","commonSituations":"Restarting a flow whose workers were torn down and log rows garbage-collected; DB outage during resume; flowID typo or stale reference from the UI; restore of DB from a dump missing this flow's logs.","solutions":["Confirm an agent log record exists for this flowID (and was not garbage-collected)","Check DB connectivity and the wrapped error for the exact cause","If the flow is genuinely fresh, start it with newFlowProviderWorkers instead of get","Restore from a correct backup or recreate the flow if log rows are lost"],"exampleFix":"// before: resume path fails hard when no worker exists yet\nworkers, err := getFlowProviderWorkers(ctx, flowID, cnts)\nif err != nil { return nil, err }\n// after: fall back to creating fresh workers when none exist\nworkers, err := getFlowProviderWorkers(ctx, flowID, cnts)\nif err != nil {\n    log.Printf(\"no existing workers for flow %d, creating new: %v\", flowID, err)\n    workers, err = newFlowProviderWorkers(ctx, flowID, cnts, pub)\n    if err != nil { return nil, err }\n}","handlingStrategy":"fallback","validationCode":"var exists int\nif err := db.QueryRowContext(ctx, `SELECT COUNT(1) FROM agent_logs WHERE flow_id=$1`, flowID).Scan(&exists); err != nil {\n    return err\n}\nif exists == 0 { // no prior agent log: use newFlowProviderWorkers instead }","typeGuard":"func agentLogExists(ctx context.Context, db DB, flowID int64) bool {\n    var n int\n    _ = db.QueryRowContext(ctx, `SELECT COUNT(1) FROM agent_logs WHERE flow_id=$1`, flowID).Scan(&n)\n    return n > 0\n}","tryCatchPattern":"alw, err := cnts.alc.GetFlowAgentLog(ctx, flowID)\nif err != nil {\n    if errors.Is(err, sql.ErrNoRows) || database.IsNotFound(err) {\n        // fall back to newFlowProviderWorkers to create fresh workers\n        return newFlowProviderWorkers(ctx, flowID, cnts, pub)\n    }\n    return nil, fmt.Errorf(\"failed to get flow agent log (flow=%d): %w\", flowID, err)\n}","preventionTips":["Distinguish not-found from transient DB errors before failing the resume","Do not garbage-collect log rows for flows that may be resumed","Verify flowID provenance (UI/session state) before resuming","After DB restores, validate that expected flow log rows exist before resume operations"],"tags":["go","database","flow-resume","logging"],"backgroundTag":"flow-worker-resume-failed","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}