vxcontrol/pentagi · error

failed to resolve current schema: %w

Error message

failed to resolve current schema: %w

What it means

VerifySearchPath runs SELECT current_schema() to confirm the connection actually resolves into the tenant's schema after the DSN search_path rewrite. This error wraps a failure of that probe query itself — the connection is unusable (network, auth, canceled context), not misrouted. It is called from main and the installer's password-reset path.

Source

Thrown at backend/pkg/database/tenant.go:171

		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(&current); err != nil {
		return fmt.Errorf("failed to resolve current schema: %w", err)
	}
	if current.String != cfg.SchemaName() {
		return fmt.Errorf(
			"search_path resolved to schema %q, expected %q — refusing to start so tenants "+
				"do not silently share one dataset",
			current.String, cfg.SchemaName(),
		)
	}

	return nil
}

// RunMigrations applies pending migrations while holding an advisory lock, so
// that two instances booting simultaneously cannot execute the same migration
// set concurrently. Without a tenant the lock is still taken, which also fixes
// the pre-existing race between two single-instance deployments sharing a
// database.
func RunMigrations(ctx context.Context, db *sql.DB, cfg *config.Config, up func(*sql.DB) error) error {

View on GitHub (pinned to ea665308ba)

Solutions

  1. Test the exact rewritten DSN with psql "<DATABASE_URL>" -c 'SELECT current_schema();' to see the raw driver error.
  2. If behind pgbouncer, set DATABASE_SEARCH_PATH_VIA_OPTIONS=true so search_path is sent as options=--search_path=... .
  3. Restore connectivity/credentials on the rewritten URL; verify the URL-style DSN still parses (special chars in password percent-encoded).
  4. Retry — transient network failures resolve on restart.

Example fix

// before
DATABASE_URL=postgres://u:p@pgbouncer:6543/db?search_path=tenant_acme  # pooler ignores search_path
// after
# .env
DATABASE_SEARCH_PATH_VIA_OPTIONS=true  # sends options=--search_path=tenant_acme,public
Defensive patterns

Strategy: validation

Validate before calling

// validate the rewritten DSN resolves to the tenant schema before app start
psql "$DATABASE_URL" -c "SELECT current_schema();"  # must return the tenant schema

Try / catch

if err := VerifySearchPath(ctx, db, cfg); err != nil {
    if strings.Contains(err.Error(), "failed to resolve current schema") {
        log.Error().Err(err).Msg("DSN unusable after search_path rewrite; check pooler options and TLS")
    }
    return err
}

Prevention

When it happens

Trigger: After RewriteDatabaseURLForTenant appends search_path to DATABASE_URL, a pool/ping query SELECT current_schema() fails: DSN became malformed after the rewrite, pooler rejects the options/search_path parameter, DB unreachable, or ctx canceled.

Common situations: DATABASE_SEARCH_PATH_VIA_OPTIONS mismatch with pgbouncer/Supavisor which may strip or reject options; a libpq keyword DSN that the rewritten string broke; connection dropped between open and probe; wrong TLS settings on the rewritten URL.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/a6a95b85fa011972. Report an issue: GitHub.