{"record":{"id":"59be185af82b6ce9","repo":"JuliusBrussee/caveman","slug":"postgres-tenant-schema-isolation-incomplete-s","errorCode":null,"errorMessage":"postgres: tenant schema isolation incomplete: %s","messagePattern":"postgres: tenant schema isolation incomplete: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"shared/platform/postgresconfig/postgresconfig.go","lineNumber":245,"sourceCode":"\ttx, err := pool.BeginTx(ctx, pgx.TxOptions{\n\t\tIsoLevel:   pgx.RepeatableRead,\n\t\tAccessMode: pgx.ReadOnly,\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"postgres: begin tenant schema inspection: %w\", err)\n\t}\n\tdefer tx.Rollback(ctx)\n\n\ttables, err := inspectTenantTables(ctx, tx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"postgres: inspect tenant tables: %w\", err)\n\t}\n\tforeignKeys, err := inspectTenantForeignKeys(ctx, tx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"postgres: inspect tenant foreign keys: %w\", err)\n\t}\n\tif violations := tenantSchemaViolations(tables, foreignKeys); len(violations) > 0 {\n\t\treturn fmt.Errorf(\"postgres: tenant schema isolation incomplete: %s\", strings.Join(violations, \"; \"))\n\t}\n\tif err := validateResolverSchema(ctx, tx); err != nil {\n\t\treturn err\n\t}\n\tif err := tx.Commit(ctx); err != nil {\n\t\treturn fmt.Errorf(\"postgres: finish tenant schema inspection: %w\", err)\n\t}\n\treturn nil\n}\n\nfunc inspectTenantTables(ctx context.Context, queryer catalogQuerier) ([]tenantTableSchema, error) {\n\trows, err := queryer.Query(ctx, `\n\t\tSELECT c.relname,\n\t\t       NOT organization.attnotnull,\n\t\t       c.relrowsecurity,\n\t\t       c.relforcerowsecurity,\n\t\t       pol.oid IS NOT NULL,\n\t\t       coalesce(pol.polpermissive, false),","sourceCodeStart":227,"sourceCodeEnd":263,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/shared/platform/postgresconfig/postgresconfig.go#L227-L263","documentation":"ValidateTenantSchema compares the inspected tenant tables and foreign keys against the required tenant-isolation contract via tenantSchemaViolations. If any violations are found, it fails startup with a semicolon-joined list of what is missing or wrong in the tenant schema. This is a deliberate migration/schema-drift guard: the database schema does not match what the library requires.","triggerScenarios":"Calling NewRuntimePool against a database where the tenant schema is incomplete: missing required tenant tables, tables missing RLS/tenant columns, or foreign keys that cross tenant boundaries — tenantSchemaViolations returns a non-empty list.","commonSituations":"Migrations not applied (or partially applied) before starting the service; a migration added a table without the tenant-id column or without proper FK scoping; pointing a staging/production pool at a database created for an older schema version; someone altered the schema manually.","solutions":["Read the joined violation list in the error — it names each missing table, column, or offending foreign key","Run the project's pending migrations (e.g. migrate up) so the tenant schema matches the expected version","Fix any cross-tenant foreign keys reported by dropping/recreating them with the tenant column in the key","Verify you are pointing at the intended database/DSN (not an old environment)","Re-run NewRuntimePool and confirm ValidateTenantSchema passes"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before NewRuntimePool, check migrations are current\nvar dirty bool\nif err := db.QueryRow(\"SELECT bool_or(version IS NULL) FROM schema_migrations\").Scan(&dirty); err != nil || dirty { return errors.New(\"run migrations first\") }","typeGuard":null,"tryCatchPattern":"if err := NewRuntimePool(ctx, cfg); err != nil {\n    if strings.Contains(err.Error(), \"tenant schema isolation incomplete\") {\n        log.Fatalf(\"apply pending migrations before starting: %v\", err)\n    }\n    return err\n}","preventionTips":["Always run schema migrations as a deploy step before starting services","Treat the tenant schema contract as versioned; add migration tests asserting required tables/FKs","Never hand-edit tenant tables in production"],"tags":["postgres","schema-migration","tenant-isolation","multi-tenancy"],"backgroundTag":"schema-validation-failed","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}