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

  1. Ensure the flow is loaded/registered (creating its worker) before requesting its search log worker.
  2. Check whether the flow already finished — if workers are cleaned up on completion, re-create or re-hydrate from the database.
  3. Validate the flowID value on the caller side (correct type, non-zero, belongs to this instance).
  4. 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

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.