vxcontrol/pentagi · error
failed to resolve schema of extension %q: %w
Error message
failed to resolve schema of extension %q: %w
What it means
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.
Source
Thrown at backend/pkg/database/tenant.go:155
return nil
}
}
// extensionSchema returns the schema an extension is installed into, or "" when
// it is not installed.
func extensionSchema(ctx context.Context, conn *sql.Conn, ext string) (string, error) {
var schema string
err := conn.QueryRowContext(ctx, `
SELECT n.nspname
FROM pg_extension e
JOIN pg_namespace n ON n.oid = e.extnamespace
WHERE e.extname = $1`, ext).Scan(&schema)
switch {
case errors.Is(err, sql.ErrNoRows):
return "", nil
case err != nil:
return "", fmt.Errorf("failed to resolve schema of extension %q: %w", ext, err)
default:
return schema, nil
}
}
// VerifySearchPath asserts that connections really do resolve into the expected
// schema. A typo in the DSN would otherwise route a tenant silently onto public,
// where every tenant would share one dataset — a quiet, catastrophic failure.
func VerifySearchPath(ctx context.Context, db *sql.DB, cfg *config.Config) error {
if !cfg.HasTenant() {
return nil
}
var current sql.NullString
if err := db.QueryRowContext(ctx, "SELECT current_schema()").Scan(¤t); err != nil {
return fmt.Errorf("failed to resolve current schema: %w", err)
}
if current.String != cfg.SchemaName() {View on GitHub (pinned to ea665308ba)
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).
Example fix
// before ctx, cancel := context.WithTimeout(ctx, 2*time.Second) // after ctx, cancel := context.WithTimeout(ctx, 30*time.Second) // allow slow catalog lookups under load
Defensive patterns
Strategy: retry
Validate before calling
// cheap connectivity check before bootstrap db.PingContext(ctx) // if this passes, the catalog query itself only fails on transient faults
Try / catch
err := EnsureTenantSchema(ctx, cfg)
for attempt := 1; err != nil && strings.Contains(err.Error(), "failed to resolve schema") && attempt <= 3; attempt++ {
time.Sleep(time.Duration(attempt) * 2 * time.Second)
err = EnsureTenantSchema(ctx, cfg)
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- failed to reach database for tenant bootstrap: %w
- failed to resolve current schema: %w
- failed to create flow in DB: %w
- failed to delete assistant %d: %w
- failed to rename flow %d: %w
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/24160a662695840f.
Report an issue: GitHub.