vxcontrol/pentagi · error

failed to get flow primary container: %w

Error message

failed to get flow primary container: %w

What it means

During LoadFlowWorker, the flow's primary (working) Docker container is read from the DB via GetFlowPrimaryContainer; without it the resumed worker cannot execute tools. A failure here is wrapped as 'failed to get flow primary container' with the underlying SQLC/DB cause (typically sql.ErrNoRows when no primary container row exists for the flow).

Source

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

	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)
	if err != nil {
		logger.WithError(err).Error("failed to get user")
		return nil, fmt.Errorf("failed to get user %d: %w", flow.UserID, err)
	}

	ctx, observation := obs.Observer.NewObservation(ctx,
		langfuse.WithObservationTraceID(flow.TraceID.String),
		langfuse.WithObservationTraceContext(
			langfuse.WithTraceName(fmt.Sprintf("%s%d flow worker", fwc.cfg.TenantLabel(), flow.ID)),
			langfuse.WithTraceUserID(tenantUserID(fwc.cfg, user.Mail)),
			langfuse.WithTraceTags(tenantTags(fwc.cfg, "controller", "flow")),
			langfuse.WithTraceSessionID(fwc.cfg.ScopedName(fmt.Sprintf("flow-%d", flow.ID))),
			langfuse.WithTraceMetadata(tenantMeta(fwc.cfg, langfuse.Metadata{

View on GitHub (pinned to ea665308ba)

Solutions

  1. Check the wrapped cause: if sql.ErrNoRows, insert/recreate a primary container record for the flow or set its status to failed so it isn't loaded.
  2. Verify the containers table still has rows for this flow ID (SELECT * FROM containers WHERE flow_id = ?).
  3. Ensure the code path that creates the primary container commits before the flow status is set to running.
  4. Restore consistent DB state after any manual DB surgery or restore.
  5. If DB connectivity is the cause, fix Postgres and restart — LoadFlows will retry at next startup.

Example fix

// before
// flow stuck 'running' but container row deleted manually
worker, err := controller.LoadFlowWorker(ctx, flow, fwc) // fails: no primary container
// after
_, err := fwc.DB.GetFlowPrimaryContainer(ctx, flow.ID)
if errors.Is(err, sql.ErrNoRows) {
    _ = fw.SetStatus(ctx, database.FlowStatusFailed) // stop trying to load it
    return
}
worker, err := controller.LoadFlowWorker(ctx, flow, fwc)
Defensive patterns

Strategy: validation

Validate before calling

container, err := fwc.DB.GetFlowPrimaryContainer(ctx, flow.ID)
if errors.Is(err, sql.ErrNoRows) {
    // no primary container: fail the flow so it isn't retried on load
    _ = fwc.DB.UpdateFlowStatus(ctx, database.UpdateFlowStatusParams{ID: flow.ID, Status: database.FlowStatusFailed})
    return nil
}

Type guard

func hasPrimaryContainer(ctx context.Context, db DB, flowID int64) bool {
    _, err := db.GetFlowPrimaryContainer(ctx, flowID)
    return err == nil
}

Try / catch

fw, err := controller.LoadFlowWorker(ctx, flow, fwc)
if err != nil {
    if strings.Contains(err.Error(), "failed to get flow primary container") {
        // mark flow failed so startup doesn't retry it forever
        _ = fwc.DB.UpdateFlowStatus(ctx, database.UpdateFlowStatusParams{ID: flow.ID, Status: database.FlowStatusFailed})
    }
    return err
}

Prevention

When it happens

Trigger: Loading a flow marked running/waiting that has no primary container row — e.g. the container was never created before crash, was deleted from the containers table, or the primary-container query fails on a DB error.

Common situations: Docker container rows purged manually or by a cleanup job while the flow status stayed 'running'; crash between flow creation and container registration; FK/data mismatch after DB restores.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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