{"record":{"id":"25146a5b859b0643","repo":"vxcontrol/pentagi","slug":"flow-not-found","errorCode":null,"errorMessage":"flow not found","messagePattern":"flow not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/controller/alogs.go","lineNumber":67,"sourceCode":"\n\tflows := make([]FlowAgentLogWorker, 0, len(alc.flows))\n\tfor _, flw := range alc.flows {\n\t\tflows = append(flows, flw)\n\t}\n\n\treturn flows, nil\n}\n\nfunc (alc *agentLogController) GetFlowAgentLog(\n\tctx context.Context,\n\tflowID int64,\n) (FlowAgentLogWorker, error) {\n\talc.mx.Lock()\n\tdefer alc.mx.Unlock()\n\n\tflw, ok := alc.flows[flowID]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"flow not found\")\n\t}\n\n\treturn flw, nil\n}\n","sourceCodeStart":49,"sourceCodeEnd":72,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/controller/alogs.go#L49-L72","documentation":"GetFlowAgentLog looks up the flow ID in the agent-log controller's in-memory flows map under a mutex; if absent it returns fmt.Errorf(\"flow not found\"). This means no agent-log worker has been registered for that flow — the flow either never started, already finished and was cleaned up, or the ID is wrong.","triggerScenarios":"Requesting the agent log stream/log for flow_id when no FlowAgentLogWorker exists in alc.flows: unknown flow ID, flow created before this service instance started (restart wiped the map), or flow already terminated and evicted.","commonSituations":"Client polling logs after flow completion, backend restart losing in-memory worker registrations, copying a flow ID from another environment, or race where the log request lands before the worker is registered.","solutions":["Verify the flow_id exists and the flow is currently running","Re-query the flow list to get a valid ID and retry","Fetch persisted logs from the database for completed flows instead of the live in-memory worker","If after a backend restart, accept that live log workers are gone and re-run/re-open the flow"],"exampleFix":"// before\nconst worker = await agentLog.getFlowAgentLog(flowId); // throws if evicted\n// after\nconst flow = await api.getFlow(flowId);\nif (flow.status === 'completed') {\n  const logs = await api.getPersistedFlowLogs(flowId);\n} else {\n  const worker = await agentLog.getFlowAgentLog(flowId);\n}","handlingStrategy":"try-catch","validationCode":"const flow = await api.getFlow(flowId); // 404 here means the ID is wrong before touching the log worker\nif (!flow || flow.status !== 'running') throw new Error(`flow ${flowId} is not active`);","typeGuard":"function hasActiveWorker(w: FlowAgentLogWorker | undefined): w is FlowAgentLogWorker {\n  return w !== undefined;\n}","tryCatchPattern":"try {\n  const worker = await agentLogCtl.GetFlowAgentLog(ctx, flowId);\n  return worker.Stream();\n} catch (e) {\n  if (/flow not found/.test(String(e))) {\n    return loadPersistedAgentLog(flowId); // completed flow or restart\n  }\n  throw e;\n}","preventionTips":["Only request live logs for flows in 'running' state","Fall back to DB-persisted logs for finished flows","Re-subscribe after backend restarts; in-memory workers do not survive redeploys","Validate flow IDs against the API list before opening log streams"],"tags":["controller","logging","not-found","in-memory-state"],"backgroundTag":"resource-not-found","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}