vxcontrol/pentagi · error
flow not found
Error message
flow not found
What it means
GetFlowSearchLog looks up a cached FlowSearchLogWorker for a flowID in an in-memory map protected by a mutex. If no worker has been registered for that flowID, it returns a plain 'flow not found' error. It is a cache-lookup miss, not necessarily proof the flow is absent from the database.
Source
Thrown at backend/pkg/controller/slogs.go:67
flows := make([]FlowSearchLogWorker, 0, len(slc.flows))
for _, flw := range slc.flows {
flows = append(flows, flw)
}
return flows, nil
}
func (slc *searchLogController) GetFlowSearchLog(
ctx context.Context,
flowID int64,
) (FlowSearchLogWorker, error) {
slc.mx.Lock()
defer slc.mx.Unlock()
flw, ok := slc.flows[flowID]
if !ok {
return nil, fmt.Errorf("flow not found")
}
return flw, nil
}
View on GitHub (pinned to ea665308ba)
Solutions
- Ensure the flow is loaded/registered (creating its worker) before requesting its search log worker.
- Check whether the flow already finished — if workers are cleaned up on completion, re-create or re-hydrate from the database.
- Validate the flowID value on the caller side (correct type, non-zero, belongs to this instance).
- After a server restart, treat the in-memory cache as empty and reload workers lazily from DB.
Example fix
// before
worker, err := slc.GetFlowSearchLog(ctx, flowID)
if err != nil {
return err
}
// after
worker, err := slc.GetFlowSearchLog(ctx, flowID)
if err != nil {
if err.Error() == "flow not found" {
worker, err = slc.CreateFlowSearchLog(ctx, flowID) // lazy-init from DB
if err != nil {
return fmt.Errorf("flow %d not found: %w", flowID, err)
}
} else {
return err
}
} Defensive patterns
Strategy: fallback
Validate before calling
// guard: ensure the flow worker exists before use
if flowID == 0 {
return fmt.Errorf("flowID required")
}
slc.mx.Lock()
_, ok := slc.flows[flowID]
slc.mx.Unlock()
if !ok { /* create/register worker first */ } Type guard
func HasFlowWorker(slc *FlowSearchLogController, flowID int64) bool {
slc.mx.Lock()
defer slc.mx.Unlock()
_, ok := slc.flows[flowID]
return ok
} Try / catch
worker, err := slc.GetFlowSearchLog(ctx, flowID)
if err != nil {
if err.Error() == "flow not found" {
// fallback: lazy-initialize or report 404
http.Error(w, "flow not found", http.StatusNotFound)
return
}
http.Error(w, "internal error", http.StatusInternalServerError)
} Prevention
- Register the flow worker before exposing any log endpoints for that flow.
- Do not serve requests for flows whose workers were cleaned up after completion.
- After process restart, re-hydrate the worker map from the database before accepting traffic.
- Prefer a sentinel exported error (ErrFlowNotFound) over a string literal for matching.
When it happens
Trigger: Calling GetFlowSearchLog(ctx, flowID) before the flow's worker was created/registered in slc.flows, after the worker was evicted/removed (e.g. flow finished and cleaned up), or with a mistyped flowID.
Common situations: Client polls search logs for a flow that already completed and whose worker was reaped; a server restart wiped the in-memory cache; concurrent request raced ahead of worker initialization.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/89cf7a67ae1ed578.
Report an issue: GitHub.