vxcontrol/pentagi · warning

failed to get flow %d containers: %w

Error message

failed to get flow %d containers: %w

What it means

After successfully updating flow status, SetStatus fetches the flow's containers with GetFlowContainers so it can publish a FlowUpdated event. If that SELECT fails, the error is wrapped as 'failed to get flow %d containers'. The status update has already been committed at this point; only the notification path fails.

Source

Thrown at backend/pkg/controller/flow.go:552

	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 {
		return
	}

	task.InvalidateSubtasks(subtaskIDs)
}

View on GitHub (pinned to ea665308ba)

Solutions

  1. Check the wrapped cause; if context.Canceled, re-run with context.WithoutCancel(ctx) so the event isn't dropped.
  2. Verify Postgres health and pool limits if this recurs under load.
  3. Since status was already updated, it is safe to retry only the container fetch + publish, not the whole SetStatus.
  4. Confirm the containers table exists and matches the SQLC query after any migration work.
  5. Note the inconsistency risk: status changed but subscribers not notified — trigger FlowUpdated manually if needed.

Example fix

// before
err := fw.SetStatus(ctx, database.FlowStatusWaiting) // ctx cancelled after UPDATE, no event published
// after
err := fw.SetStatus(context.WithoutCancel(ctx), database.FlowStatusWaiting)
if err != nil {
    log.WithError(err).Warn("status updated but containers fetch failed; retry publish")
}
Defensive patterns

Strategy: retry

Validate before calling

if err := ctx.Err(); err != nil {
    // ctx already cancelled: run SetStatus with context.WithoutCancel(ctx)
    ctx = context.WithoutCancel(ctx)
}

Try / catch

err := fw.SetStatus(ctx, database.FlowStatusWaiting)
if err != nil && strings.Contains(err.Error(), "containers") {
    // status already updated; only retry the publish side
    log.WithError(err).Warn("status persisted, FlowUpdated event may be missed")
}

Prevention

When it happens

Trigger: GetFlowContainers errors: DB connectivity loss right after the status UPDATE, context cancelled mid-query, or a schema/query mismatch in the containers table.

Common situations: Transient Postgres hiccup between the two queries; shutdown cancelling ctx between update and read; containers table missing after partial migration/restore.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/3a07cfe574fc919d. Report an issue: GitHub.