vxcontrol/pentagi · warning
flow %d has status %s: loading aborted: %w
Error message
flow %d has status %s: loading aborted: %w
What it means
LoadFlowWorker resurrects flow workers at startup (LoadFlows) for flows persisted as running. Only FlowStatusRunning and FlowStatusWaiting qualify; any other persisted status (created, finished, failed, completed) is not loadable, so it wraps ErrNothingToLoad with the flow's ID and actual status. This is an expected skip, not a corruption signal.
Source
Thrown at backend/pkg/controller/flow.go:328
if !fwc.dryRun {
if err := fw.PutInput(ctx, fwc.input, nil, fwc.resources); err != nil {
return nil, wrapErrorEndSpan(ctx, flowSpan, "failed to run flow worker", err)
}
}
flowSpan.End(langfuse.WithSpanStatus("flow worker started"))
return fw, nil
}
func LoadFlowWorker(ctx context.Context, flow database.Flow, fwc flowWorkerCtx) (FlowWorker, error) {
ctx, span := obs.Observer.NewSpan(ctx, obs.SpanKindInternal, "controller.LoadFlowWorker")
defer span.End()
switch flow.Status {
case database.FlowStatusRunning, database.FlowStatusWaiting:
default:
return nil, fmt.Errorf("flow %d has status %s: loading aborted: %w", flow.ID, flow.Status, ErrNothingToLoad)
}
logger := logrus.WithContext(ctx).WithFields(logrus.Fields{
"flow_id": flow.ID,
"user_id": flow.UserID,
"provider_name": flow.ModelProviderName,
"provider_type": flow.ModelProviderType,
})
container, err := fwc.db.GetFlowPrimaryContainer(ctx, flow.ID)
if err != nil {
logger.WithError(err).Error("failed to get flow primary container")
return nil, fmt.Errorf("failed to get flow primary container: %w", err)
}
logger.Info("flow loaded from DB")
user, err := fwc.db.GetUser(ctx, flow.UserID)View on GitHub (pinned to ea665308ba)
Solutions
- Only treat this as a problem if the flow should be resumable: set its status to FlowStatusRunning or FlowStatusWaiting in the DB.
- If the flow is genuinely done, ignore/retry-skip: the loader will skip non-running flows.
- Check why the flow ended in an unexpected status (worker crash logs for that flow ID).
- Filter the flows query in LoadFlows to statuses Running/Waiting to avoid noisy errors for finished flows.
Example fix
// before
for _, flow := range flows {
fw, err := controller.LoadFlowWorker(ctx, flow, fwc)
if err != nil { log.WithError(err).Error("load failed") }
}
// after
for _, flow := range flows {
if flow.Status != database.FlowStatusRunning && flow.Status != database.FlowStatusWaiting {
continue // skip terminal/created flows, matches ErrNothingToLoad guard
}
fw, err := controller.LoadFlowWorker(ctx, flow, fwc)
if err != nil { log.WithError(err).Error("load failed") }
} Defensive patterns
Strategy: validation
Validate before calling
if flow.Status != database.FlowStatusRunning && flow.Status != database.FlowStatusWaiting {
// skip: only running/waiting flows are loadable
return nil
} Type guard
func isLoadable(s database.FlowStatus) bool {
return s == database.FlowStatusRunning || s == database.FlowStatusWaiting
} Try / catch
fw, err := controller.LoadFlowWorker(ctx, flow, fwc)
if err != nil {
if errors.Is(err, controller.ErrNothingToLoad) {
log.Infof("flow %d in status %s: nothing to load, skipping", flow.ID, flow.Status)
return nil
}
return err
} Prevention
- Pre-filter flows by status Running/Waiting in the loader query
- Check errors.Is(err, ErrNothingToLoad) and skip rather than fail startup
- Investigate flows unexpectedly left in non-loadable statuses after crashes
When it happens
Trigger: LoadFlows iterates flows after server restart and calls LoadFlowWorker on a flow whose stored status is not Running/Waiting — e.g. it finished, failed, or was created but never started before the crash.
Common situations: Server restart with flows left in FlowStatusFailed/Finished/Completed from a previous run; crash mid-flow leaving status 'created'; manually flipping status in DB to test and forgetting to set it back to running/waiting.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- failed to set flow %d status: %w
- flow %d is not completed
- failed to stop flow %d: %w
- failed to finish flow %d: %w
- flow not found
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/ae3ae0f48336af4e.
Report an issue: GitHub.