JuliusBrussee/caveman · critical
postgres: resolver isolation incomplete
Error message
postgres: resolver isolation incomplete: %s
What it means
validateResolverSchema aggregates a list of resolver-isolation violations from a catalog query (SQL-level RLS policy checks, e.g. policies lacking polwithcheck). If the aggregated violation string is non-empty, the schema fails validation with the violation list embedded in the message. Like its tenant-schema sibling, this is a deliberate guard ensuring row-level security is correctly configured before the pool starts.
Solutions
- Parse the semicolon-joined violations in the message to see which tables/policies are deficient
- Recreate the policies per the library's requirements, including WITH CHECK clauses (e.g. ALTER TABLE ... ENABLE ROW LEVEL SECURITY; CREATE POLICY ... WITH CHECK ...)
- Re-run the project's schema migrations to restore canonical policies
- Confirm the policies are applied for the role the pool connects as, then retry NewRuntimePool
Example fix
// before: policy without WITH CHECK -> violation reported
CREATE POLICY resolver_isolation ON resolver.t FOR SELECT USING (org_id = current_setting('app.current_organization_id')::uuid);
// after: include WITH CHECK
CREATE POLICY resolver_isolation ON resolver.t FOR ALL USING (org_id = current_setting('app.current_organization_id')::uuid) WITH CHECK (org_id = current_setting('app.current_organization_id')::uuid); Defensive patterns
Strategy: validation
Validate before calling
// detect policies missing WITH CHECK before startup SELECT schemaname, tablename, policyname FROM pg_policies WHERE schemaname='resolver' AND (polwithcheck IS NULL OR polroles IS NULL);
Try / catch
if err := NewRuntimePool(ctx, cfg); err != nil {
if strings.Contains(err.Error(), "resolver isolation incomplete") {
log.Fatalf("RLS policy drift on resolver schema, re-run migrations: %v", err)
}
return err
} Prevention
- Create every RLS policy with both USING and WITH CHECK clauses
- Manage policies only through migrations; audit pg_policies after restores
- Add an integration test asserting resolver policy definitions post-migrate
When it happens
Trigger: NewRuntimePool → ValidateTenantSchema → validateResolverSchema: the SQL finds resolver tables whose RLS policies are missing, not FORCE, or missing WITH CHECK clauses — the violations string is non-empty.
Common situations: Migrations applied but RLS policies created incompletely (e.g. CREATE POLICY without WITH CHECK); someone dropped or altered a policy; enabling RLS manually on a new resolver table without the full policy set; restoring a dump that lost policy definitions.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- postgres: inspect resolver schema
- postgres: tenant schema isolation incomplete
- envelope: organization scope is required
- envelope: tenant scope mismatch
- postgres: begin tenant schema inspection
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/fbc461593c3ba05d.
Report an issue: GitHub.
Appendix: source
Thrown at shared/platform/postgresconfig/postgresconfig.go:756
JOIN pg_attribute org_col ON org_col.attrelid=c.oid
AND org_col.attname='organization_id' AND NOT org_col.attisdropped
WHERE n.nspname='public' AND c.relkind IN ('r','p')
AND has_table_privilege(rr.role_name, c.oid, 'SELECT,INSERT,UPDATE,DELETE')
AND NOT EXISTS (
SELECT 1 FROM pg_policy policy
WHERE policy.polrelid=c.oid
AND role.oid=ANY(policy.polroles)
AND policy.polqual IS NOT NULL
AND policy.polwithcheck IS NOT NULL
)
)
SELECT coalesce(string_agg(violation, '; ' ORDER BY violation), '') FROM violations
`).Scan(&violations)
if err != nil {
return fmt.Errorf("postgres: inspect resolver schema: %w", err)
}
if violations != "" {
return fmt.Errorf("postgres: resolver isolation incomplete: %s", violations)
}
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 {View on GitHub (pinned to 3ee70a1026)