JuliusBrussee/caveman · error

postgres: set organization scope

Error message

postgres: set organization scope: %w

What it means

WithOrg begins a transaction and sets the transaction-local tenant GUC app.current_organization_id via set_config before running fn. This error wraps a failure executing that set_config statement, meaning the organization scope could not be established and the transaction is rolled back. Without the GUC, RLS policies would fail or leak, so the library refuses to proceed.

Solutions

  1. Check the wrapped error: for context timeout, increase the request timeout or pool capacity
  2. For connection errors, verify DB connectivity and retry WithOrg
  3. Confirm no server-side hooks (e.g. reserved-prefix GUC policies) block setting app.current_organization_id
  4. Note the deferred Rollback already ran — the caller must retry the whole WithOrg call
Defensive patterns

Strategy: try-catch

Validate before calling

if orgID == "" { return errors.New("WithOrg requires a non-empty organization id") }

Try / catch

err := pool.WithOrg(ctx, orgID, func(tx pgx.Tx) error { ... })
if err != nil {
    if strings.Contains(err.Error(), "set organization scope") {
        // transient DB issue: safe to retry the whole WithOrg call
    }
    return err
}

Prevention

When it happens

Trigger: Calling WithOrg with a valid orgID but tx.Exec('SELECT set_config(...)') errors — connection failure, context canceled, or driver-level error during Exec.

Common situations: Network drop right after Begin; context deadline during a busy transaction pool; Postgres rejecting set_config due to a session-level restriction or custom GUC placement rules in hardened setups.

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 JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/642c745a624f6d1d. Report an issue: GitHub.

Appendix: source

Thrown at shared/platform/postgresconfig/postgresconfig.go:775

	}
	return nil
}

// WithOrg runs fn inside a transaction whose tenant GUC is transaction-local.
// Empty scopes are rejected: tenant work must never degrade to an unscoped
// query when RLS is the hard boundary.
func WithOrg(ctx context.Context, pool *pgxpool.Pool, orgID string, fn func(pgx.Tx) error) error {
	orgID = strings.TrimSpace(orgID)
	if orgID == "" {
		return errors.New("postgres: organization scope is required")
	}
	tx, err := pool.Begin(ctx)
	if err != nil {
		return err
	}
	defer func() { _ = tx.Rollback(ctx) }()
	if _, err := tx.Exec(ctx, `SELECT set_config('app.current_organization_id', $1, true)`, orgID); err != nil {
		return fmt.Errorf("postgres: set organization scope: %w", err)
	}
	if err := fn(tx); err != nil {
		return err
	}
	return tx.Commit(ctx)
}

View on GitHub (pinned to 3ee70a1026)