{"record":{"id":"24160a662695840f","repo":"vxcontrol/pentagi","slug":"failed-to-resolve-schema-of-extension-q-w","errorCode":null,"errorMessage":"failed to resolve schema of extension %q: %w","messagePattern":"failed to resolve schema of extension %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/database/tenant.go","lineNumber":155,"sourceCode":"\t\treturn nil\n\t}\n}\n\n// extensionSchema returns the schema an extension is installed into, or \"\" when\n// it is not installed.\nfunc extensionSchema(ctx context.Context, conn *sql.Conn, ext string) (string, error) {\n\tvar schema string\n\terr := conn.QueryRowContext(ctx, `\n\t\tSELECT n.nspname\n\t\t  FROM pg_extension e\n\t\t  JOIN pg_namespace n ON n.oid = e.extnamespace\n\t\t WHERE e.extname = $1`, ext).Scan(&schema)\n\n\tswitch {\n\tcase errors.Is(err, sql.ErrNoRows):\n\t\treturn \"\", nil\n\tcase err != nil:\n\t\treturn \"\", fmt.Errorf(\"failed to resolve schema of extension %q: %w\", ext, err)\n\tdefault:\n\t\treturn schema, nil\n\t}\n}\n\n// VerifySearchPath asserts that connections really do resolve into the expected\n// schema. A typo in the DSN would otherwise route a tenant silently onto public,\n// where every tenant would share one dataset — a quiet, catastrophic failure.\nfunc VerifySearchPath(ctx context.Context, db *sql.DB, cfg *config.Config) error {\n\tif !cfg.HasTenant() {\n\t\treturn nil\n\t}\n\n\tvar current sql.NullString\n\tif err := db.QueryRowContext(ctx, \"SELECT current_schema()\").Scan(&current); err != nil {\n\t\treturn fmt.Errorf(\"failed to resolve current schema: %w\", err)\n\t}\n\tif current.String != cfg.SchemaName() {","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/database/tenant.go#L137-L173","documentation":"extensionSchema queries pg_extension/pg_namespace to find which schema an extension is installed in (returning \"\" when absent). This error wraps any failure of that catalog lookup other than 'no rows' — typically the connection died, the statement was canceled by the context, or the advisory-lock session was terminated. It is an infrastructure error, not a configuration error.","triggerScenarios":"During tenant bootstrap, SELECT n.nspname FROM pg_extension e JOIN pg_namespace n ... WHERE e.extname=$1 fails: context deadline/cancel fired, connection reset by pooler or server restart, or the session was terminated while holding the advisory lock.","commonSituations":"Bootstrap taking longer than the caller's context timeout on a slow/loaded DB; pgbouncer killing idle sessions between lock acquisition and the query; network blip or failover mid-bootstrap.","solutions":["Retry the startup — the whole bootstrap is idempotent (IF NOT EXISTS everywhere) and advisory-lock protected.","Increase the context timeout / startup grace period if the DB is slow.","Check DB logs and pooler (pgbouncer) idle/session timeout settings; keep the bootstrap session on a direct connection.","Inspect the wrapped driver error for the precise transport cause (EOF, canceled, TLS)."],"exampleFix":"// before\nctx, cancel := context.WithTimeout(ctx, 2*time.Second)\n// after\nctx, cancel := context.WithTimeout(ctx, 30*time.Second) // allow slow catalog lookups under load","handlingStrategy":"retry","validationCode":"// cheap connectivity check before bootstrap\ndb.PingContext(ctx) // if this passes, the catalog query itself only fails on transient faults","typeGuard":null,"tryCatchPattern":"err := EnsureTenantSchema(ctx, cfg)\nfor attempt := 1; err != nil && strings.Contains(err.Error(), \"failed to resolve schema\") && attempt <= 3; attempt++ {\n    time.Sleep(time.Duration(attempt) * 2 * time.Second)\n    err = EnsureTenantSchema(ctx, cfg)\n}","preventionTips":["Give bootstrap a generous context timeout (minutes, not seconds)","Bypass connection poolers for the bootstrap session","Avoid statement_timeout on the migration/bootstrap role","Rely on idempotency: safe to just restart after a transient failure"],"tags":["postgres","catalog","connectivity","bootstrap"],"backgroundTag":"postgres-query-failed","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}