vxcontrol/pentagi · error
flow not found
Error message
flow not found
What it means
GetFlowAssistantLog resolves a two-level in-memory map: flows[flowID][assistantID]. If the flow ID is absent from aslc.flows it returns 'flow not found' (a missing assistant ID yields the separate 'assistant not found' error). The worker registry only holds live assistant log workers.
Source
Thrown at backend/pkg/controller/aslogs.go:75
}
flows := make([]FlowAssistantLogWorker, 0, len(aslc.flows[flowID]))
for _, flw := range aslc.flows[flowID] {
flows = append(flows, flw)
}
return flows, nil
}
func (aslc *assistantLogController) GetFlowAssistantLog(
ctx context.Context, flowID, assistantID int64,
) (FlowAssistantLogWorker, error) {
aslc.mx.Lock()
defer aslc.mx.Unlock()
flw, ok := aslc.flows[flowID]
if !ok {
return nil, fmt.Errorf("flow not found")
}
aslw, ok := flw[assistantID]
if !ok {
return nil, fmt.Errorf("assistant not found")
}
return aslw, nil
}
View on GitHub (pinned to ea665308ba)
Solutions
- Confirm the flow is running and the ID is correct via the flows API
- For terminated flows, read logs from persistent storage rather than the live worker
- Retry after confirming the assistant worker was created (subscribe once the flow is active)
- If IDs come from a saved session, refresh them after backend restarts
Example fix
// before
await assistantLog.getFlowAssistantLog(staleFlowId, assistantId); // flow not found
// after
const flows = await api.listFlows();
if (flows.some(f => f.id === flowId && f.status === 'running')) {
await assistantLog.getFlowAssistantLog(flowId, assistantId);
} Defensive patterns
Strategy: try-catch
Validate before calling
const flow = await api.getFlow(flowId);
if (!flow || flow.status !== 'running') throw new Error('flow not active');
if (!flow.assistants?.includes(assistantId)) throw new Error('assistant not found'); Type guard
function isRegisteredAssistant(
flw: Record<string, FlowAssistantLogWorker> | undefined,
assistantId: string,
): flw is Record<string, FlowAssistantLogWorker> {
return flw !== undefined && assistantId in flw;
} Try / catch
try {
const worker = await asstLogCtl.GetFlowAssistantLog(ctx, flowId, assistantId);
return worker.Stream();
} catch (e) {
if (/flow not found/.test(String(e))) {
return loadPersistedAssistantLog(flowId, assistantId);
}
if (/assistant not found/.test(String(e))) {
return retryWithBackoff(() => asstLogCtl.GetFlowAssistantLog(ctx, flowId, assistantId));
}
throw e;
} Prevention
- Gate log subscriptions on the flow's live status from GraphQL subscriptions
- Handle the two-level lookup explicitly: check flow existence before assistant
- Refresh cached flow/assistant IDs after service restarts
- Prefer persisted log queries for any non-running flow
When it happens
Trigger: Requesting an assistant log for flow_id that has no registered FlowAssistantLogWorker — unknown/finished flow, service restart, or request arriving before worker registration completes.
Common situations: Subscribing to assistant logs after the flow ended, backend redeploy clearing the map, mistyped flow ID, or frontend reconnecting with cached IDs from a previous session.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/23e3761a77814e66.
Report an issue: GitHub.