{"record":{"id":"0515560f81d168ac","repo":"JuliusBrussee/caveman","slug":"postgres-inspect-tenant-foreign-keys-w","errorCode":null,"errorMessage":"postgres: inspect tenant foreign keys: %w","messagePattern":"postgres: inspect tenant foreign keys: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/platform/postgresconfig/postgresconfig.go","lineNumber":242,"sourceCode":"// FORCE RLS, and every foreign-key edge between tenant tables must carry the\n// shared organization scope (plus project scope when both tables have it).\nfunc ValidateTenantSchema(ctx context.Context, pool *pgxpool.Pool) error {\n\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,","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/shared/platform/postgresconfig/postgresconfig.go#L224-L260","documentation":"After enumerating tenant tables, ValidateTenantSchema queries catalog metadata for foreign keys (inspectTenantForeignKeys) to verify cross-tenant isolation. This error wraps a failure executing that FK introspection query inside the same transaction. It is a query-execution failure, not an isolation verdict.","triggerScenarios":"NewRuntimePool triggers ValidateTenantSchema; the catalog query inside inspectTenantForeignKeys returns an error — context canceled, insufficient privileges on constraint catalog views, or a connection/driver error.","commonSituations":"Restricted DB role without access to information_schema.table_constraints / referential_constraints; slow startup context deadline hit between the tables and foreign-keys queries; network interruption mid-inspection.","solutions":["Grant the app role read access to information_schema constraint views (table_constraints, key_column_usage, referential_constraints, constraint_column_usage)","Inspect the wrapped error: increase context timeout if it was a deadline, or fix connectivity if a network error","Confirm Postgres version compatibility for the catalog queries used","Re-run after transient failure"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"var n int\nif err := db.QueryRow(\"SELECT count(*) FROM information_schema.table_constraints\").Scan(&n); err != nil { /* role lacks catalog access */ }","typeGuard":null,"tryCatchPattern":"if err := NewRuntimePool(ctx, cfg); err != nil {\n    if strings.Contains(err.Error(), \"inspect tenant foreign keys\") {\n        // check role privileges on constraint catalog views before retrying\n    }\n    return err\n}","preventionTips":["Include information_schema constraint-view grants in your DB role bootstrap migration","Pin and test against the target Postgres version in CI","Keep startup contexts alive long enough to complete multi-query inspection"],"tags":["postgres","database","foreign-keys","schema-inspection"],"backgroundTag":"database-query-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"}