JuliusBrussee/caveman · error
postgres: expected runtime role is required
Error message
postgres: expected runtime role is required
What it means
ValidateRuntimeIdentity checks that the pool's database user cannot bypass RLS and belongs to the expected audited role group; it refuses to run that check at all when expectedRole is blank. An empty expected role would make the membership assertion vacuous, so the library fails fast before issuing any query.
Solutions
- Pass the intended database role name, e.g. ValidateRuntimeIdentity(ctx, pool, "svc_orders_runtime")
- Populate the role from configuration and fail deployment earlier if it is missing
- Trim and check the role string at config-load time so this reaches the caller as a config error
Example fix
// before
if err := ValidateRuntimeIdentity(ctx, pool, os.Getenv("PG_ROLE")); err != nil {...} // PG_ROLE unset
// after
role := os.Getenv("PG_ROLE")
if strings.TrimSpace(role) == "" { return fmt.Errorf("PG_ROLE must be set") }
if err := ValidateRuntimeIdentity(ctx, pool, role); err != nil {...} Defensive patterns
Strategy: validation
Validate before calling
role := strings.TrimSpace(expectedRole)
if role == "" {
return fmt.Errorf("expected runtime role must be configured before ValidateRuntimeIdentity")
} Try / catch
if err := postgresconfig.ValidateRuntimeIdentity(ctx, pool, role); err != nil {
if strings.Contains(err.Error(), "expected runtime role is required") {
return fmt.Errorf("runtime role not configured: set PG_ROLE before starting")
}
return err
} Prevention
- Fail at config load if the runtime-role key is missing or blank
- Never default the role to the empty string; use a sentinel that fails loudly
- Trim whitespace from role values loaded from env/secrets
- Add a startup assertion that ValidateRuntimeIdentity runs with a concrete role in every environment
When it happens
Trigger: Calling ValidateRuntimeIdentity(ctx, pool, "") or with a whitespace-only string (spaces/tabs are trimmed to empty); passing a config value that was never populated, e.g. an unset ROLE env var defaulted to "".
Common situations: New services wired to NewRuntimePool before the runtime-role config key was added; template manifests rendering an empty role; tests forgetting to pass the role constant.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- postgres: organization scope is required
- apiKey, baseURL, and agent are required
- ASGI context resolver or request bounds are invalid
- bedrock endpoint must be runtime or mantle
- cave_mastra_max_steps_invalid
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/9838c9e72abcf245.
Report an issue: GitHub.
Appendix: source
Thrown at shared/platform/postgresconfig/postgresconfig.go:140
return nil, err
}
if err := ValidateRuntimeIdentity(ctx, pool, expectedRole); err != nil {
pool.Close()
return nil, err
}
if err := ValidateTenantSchema(ctx, pool); err != nil {
pool.Close()
return nil, err
}
return pool, nil
}
// ValidateRuntimeIdentity rejects database identities that can bypass RLS or
// do not inherit the service's audited privilege group.
func ValidateRuntimeIdentity(ctx context.Context, pool *pgxpool.Pool, expectedRole string) error {
expectedRole = strings.TrimSpace(expectedRole)
if expectedRole == "" {
return errors.New("postgres: expected runtime role is required")
}
var currentUser, sessionUser string
var superuser, bypassRLS, member, ownsTenantTable bool
err := pool.QueryRow(ctx, `
SELECT current_user,
session_user,
r.rolsuper,
r.rolbypassrls,
pg_has_role(current_user, $1, 'MEMBER'),
EXISTS (
SELECT 1
FROM pg_class c
JOIN pg_namespace n ON n.oid=c.relnamespace
JOIN information_schema.columns col
ON col.table_schema=n.nspname
AND col.table_name=c.relname
AND col.column_name='organization_id'
WHERE n.nspname='public'View on GitHub (pinned to 3ee70a1026)