vxcontrol/pentagi · error
failed to set flow %d status: %w
Error message
failed to set flow %d status: %w
What it means
flowWorker.SetStatus persists a new flow status via UpdateFlowStatus and then republishes the flow. If the UPDATE fails (DB error or cancelled context), the error is wrapped as 'failed to set flow %d status'. Callers (Finish, worker loop, processInput) rely on this to transition lifecycle state, so a failure here can leave a flow stuck in its previous status.
Source
Thrown at backend/pkg/controller/flow.go:547
func (fw *flowWorker) GetStatus(ctx context.Context) (database.FlowStatus, error) {
flow, err := fw.flowCtx.DB.GetUserFlow(ctx, database.GetUserFlowParams{
UserID: fw.flowCtx.UserID,
ID: fw.flowCtx.FlowID,
})
if err != nil {
return database.FlowStatusFailed, err
}
return flow.Status, nil
}
func (fw *flowWorker) SetStatus(ctx context.Context, status database.FlowStatus) error {
flow, err := fw.flowCtx.DB.UpdateFlowStatus(ctx, database.UpdateFlowStatusParams{
Status: status,
ID: fw.flowCtx.FlowID,
})
if err != nil {
return fmt.Errorf("failed to set flow %d status: %w", fw.flowCtx.FlowID, err)
}
containers, err := fw.flowCtx.DB.GetFlowContainers(ctx, fw.flowCtx.FlowID)
if err != nil {
return fmt.Errorf("failed to get flow %d containers: %w", fw.flowCtx.FlowID, err)
}
fw.flowCtx.Publisher.FlowUpdated(ctx, flow, containers)
return nil
}
// InvalidateTaskSubtasks drops stale workers after direct DB deletion,
// preventing delayed ErrNoRows failures.
func (fw *flowWorker) InvalidateTaskSubtasks(ctx context.Context, taskID int64, subtaskIDs []int64) {
task, err := fw.tc.GetTask(ctx, taskID)
if err != nil {
returnView on GitHub (pinned to ea665308ba)
Solutions
- Check the wrapped cause in logs: sql.ErrNoRows (flow deleted) vs driver/conn errors vs context.Canceled.
- Retry the status update with context.WithoutCancel(ctx) during shutdown paths so the final status is persisted.
- Confirm the flow still exists (not soft-deleted) if ErrNoRows.
- Verify Postgres connectivity and pool limits if failures cluster under load.
- Re-run migrations if the flows table/schema is missing columns.
Example fix
// before
err := fw.SetStatus(ctx, database.FlowStatusFinished) // ctx cancelled at shutdown, status lost
// after
err := fw.SetStatus(context.WithoutCancel(ctx), database.FlowStatusFinished)
if err != nil {
log.WithError(err).Error("failed to persist final flow status")
} Defensive patterns
Strategy: retry
Validate before calling
if _, err := db.GetFlow(ctx, flowID); err != nil {
return fmt.Errorf("flow %d gone, cannot set status: %w", flowID, err)
} Try / catch
err := fw.SetStatus(ctx, database.FlowStatusFinished)
if err != nil {
if errors.Is(err, context.Canceled) {
err = fw.SetStatus(context.WithoutCancel(ctx), database.FlowStatusFinished)
}
if err != nil { log.WithError(err).Error("flow status not persisted") }
} Prevention
- Use context.WithoutCancel for terminal status writes during shutdown
- Retry transient DB errors with backoff
- Check for soft-deleted flows when ErrNoRows is the cause
- Alert on SetStatus failures — they leave flows in stale lifecycle states
When it happens
Trigger: UpdateFlowStatus returns an error: Postgres unreachable, context cancelled (e.g. worker shutting down or client-driven ctx), row lock contention, or the flow row was deleted concurrently.
Common situations: Graceful shutdown cancelling ctx mid-update; DB failover/connection pool exhaustion during heavy runs; flow soft-deleted by the user in the UI while its worker tries to set status; migration missing.
Related errors
- failed to renew flow %d status: %w
- failed to get flow %d status: %w
- failed to set task status in back propagation: %w
- failed to get subtask msg logs: %w
- token not found in database
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/7c5b25a2edfef79d.
Report an issue: GitHub.