vxcontrol/pentagi · error

failed to get user %d: %w

Error message

failed to get user %d: %w

What it means

Right after creating the flow row, NewFlowWorker fetches the owning user with db.GetUser(ctx, fwc.userID) to build tenant/langfuse metadata. If the user row cannot be read, it wraps the error as 'failed to get user %d'. The flow row was already created but the worker start aborts (and the deferred cleanup soft-deletes the flow).

Source

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

	// DeleteFlow is a soft delete and the listings filter on deleted_at, so this is what keeps a flow
	// the caller was told it never got out of the UI. Disarmed once the worker goroutine owns the flow —
	// from there a failure is the worker's to unwind, not ours.
	cleanupFlow := true
	defer func() {
		if err == nil || !cleanupFlow {
			return
		}

		// The caller's context is usually already cancelled by whatever failed.
		if _, cerr := fwc.db.DeleteFlow(context.WithoutCancel(ctx), flowID); cerr != nil {
			logger.WithError(cerr).Error("failed to drop the flow left behind by a failed start")
		}
	}()

	user, err := fwc.db.GetUser(ctx, fwc.userID)
	if err != nil {
		logger.WithError(err).Error("failed to get user")
		return nil, fmt.Errorf("failed to get user %d: %w", fwc.userID, err)
	}

	ctx, observation := obs.Observer.NewObservation(ctx,
		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.WithTraceInput(fwc.input),
			langfuse.WithTraceSessionID(fwc.cfg.ScopedName(fmt.Sprintf("flow-%d", flow.ID))),
			langfuse.WithTraceMetadata(tenantMeta(fwc.cfg, langfuse.Metadata{
				"flow_id":       flow.ID,
				"user_id":       fwc.userID,
				"user_email":    user.Mail,
				"user_name":     user.Name,
				"user_hash":     user.Hash,
				"user_role":     user.RoleName,
				"provider_name": fwc.prvname.String(),
				"provider_type": fwc.prvtype.String(),

View on GitHub (pinned to ea665308ba)

Solutions

  1. Confirm the user with that ID exists (SELECT * FROM users WHERE id = ?) before creating flows.
  2. Check the wrapped cause in logs to distinguish not-found (sql.ErrNoRows) from connection errors.
  3. Verify the auth middleware always populates a valid userID in the request context.
  4. If users are soft-deleted elsewhere, purge their API tokens/sessions too so stale IDs aren't used.
  5. Retry transient DB errors; check Postgres health if all requests fail.

Example fix

// before
userID := int64(0) // unauthenticated/uninitialized context
worker, err := controller.NewFlowWorker(ctx, fwcWithUser(userID))
// after
if userID <= 0 { return http.Error(w, "unauthorized", 401) }
if _, err := db.GetUser(ctx, userID); err != nil {
    return http.Error(w, "unknown user", 404)
}
worker, err := controller.NewFlowWorker(ctx, fwcWithUser(userID))
Defensive patterns

Strategy: validation

Validate before calling

user, err := db.GetUser(ctx, userID)
if err != nil {
    return fmt.Errorf("cannot create flow for user %d: %w", userID, err)
}

Type guard

func userExists(ctx context.Context, db DB, id int64) bool {
    _, err := db.GetUser(ctx, id)
    return err == nil
}

Try / catch

fw, err := controller.NewFlowWorker(ctx, fwc)
if err != nil {
    if strings.Contains(err.Error(), "failed to get user") {
        return http.StatusNotFound // bad/stale userID
    }
    return http.StatusInternalServerError
}

Prevention

When it happens

Trigger: db.GetUser fails for fwc.userID: user hard-deleted between auth and flow creation, DB connection error, context cancelled, or callers passing a userID that does not exist (0 or stale).

Common situations: Multi-instance setups where a user was deleted on another node; API token auth with a userID referencing a purged user; transient Postgres connection drop; passing userID=0 from an uninitialized auth context.

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/9a117ee8ef6cd179. Report an issue: GitHub.