{"record":{"id":"81ed2735f4b99303","repo":"vxcontrol/pentagi","slug":"failed-to-get-flow-msg-log-w","errorCode":null,"errorMessage":"failed to get flow msg log: %w","messagePattern":"failed to get flow msg log: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/controller/flow.go","lineNumber":1225,"sourceCode":"\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)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get flow vector store log: %w\", err)\n\t}\n\n\ttclw, err := cnts.tclc.GetFlowToolCallLog(ctx, flowID)","sourceCodeStart":1207,"sourceCodeEnd":1243,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/controller/flow.go#L1207-L1243","documentation":"This error wraps a failure from cnts.mlc.GetFlowMsgLog(ctx, flowID), the message-log provider worker lookup for a flow, when assembling the flowProviderWorkers bundle in the flow controller. It is a %w-wrapped error, so the underlying cause (typically a database or gRPC failure) is preserved and can be inspected with errors.Is/As. The controller aborts the whole flow-load operation when any single log stream cannot be retrieved.","triggerScenarios":"Calling the flow detail/export path that builds flowProviderWorkers when the msg-log component cannot fetch logs for the given flowID: flowID does not exist, the DB row/query fails, or the underlying message-log service errors.","commonSituations":"Requesting logs for a deleted flow; PostgreSQL connection pool exhaustion or timeout; schema/migration drift between app version and DB; passing a flowID from a different environment/database.","solutions":["Check the wrapped cause (%w chain) — it is almost always a DB error; verify PostgreSQL connectivity and logs.","Verify the flowID exists (query the flows table) before fetching logs.","Confirm DB migrations are up to date (goose) so msg-log tables exist.","Retry the request if the cause is a transient connection/timeout error."],"exampleFix":"// before\nmlw, err := cnts.mlc.GetFlowMsgLog(ctx, flowID)\nif err != nil {\n\treturn nil, fmt.Errorf(\"failed to get flow msg log: %w\", err)\n}\n// after\nmlw, err := cnts.mlc.GetFlowMsgLog(ctx, flowID)\nif err != nil {\n\tif errors.Is(err, database.ErrNotFound) {\n\t\treturn nil, fmt.Errorf(\"flow %d has no msg log: %w\", flowID, err)\n\t}\n\treturn nil, fmt.Errorf(\"failed to get flow msg log: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"var exists bool\nerr := db.QueryRow(\"SELECT EXISTS(SELECT 1 FROM flows WHERE id=$1)\", flowID).Scan(&exists)\nif err != nil || !exists { /* skip fetch or surface 404 */ }","typeGuard":"func isMsgLogError(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"failed to get flow msg log\")\n}","tryCatchPattern":"mlw, err := cnts.mlc.GetFlowMsgLog(ctx, flowID)\nif err != nil {\n\tvar retryable *db.RetryableError\n\tif errors.As(err, &retryable) { /* retry with backoff */ }\n\treturn nil, fmt.Errorf(\"failed to get flow msg log: %w\", err)\n}","preventionTips":["Confirm the flowID exists before fetching its logs.","Keep DB migrations current with the app version.","Monitor DB connection-pool saturation and timeouts.","Use errors.Is/As on the wrapped cause instead of string matching."],"tags":["database","flow-logs","error-wrapping"],"backgroundTag":"data-source-query-failed","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}