vxcontrol/pentagi · error
extension %q is installed in schema %q, but multi-tenant mod
Error message
extension %q is installed in schema %q, but multi-tenant mode requires it in %q so every tenant can reach it; either run ALTER EXTENSION %s SET SCHEMA %s, or set DATABASE_EXTENSIONS_SCHEMA=%s to match where it already lives
What it means
This is a deliberate configuration-consistency error: the extension is installed, but in a schema other than the configured shared extension schema (DATABASE_EXTENSIONS_SCHEMA, default public). In multi-tenant mode every extension must live in one schema reachable from every tenant's search_path, otherwise tenants hit opaque 'type vector does not exist' during migrations. The code fails fast with an actionable remediation message instead.
Source
Thrown at backend/pkg/database/tenant.go:129
case schema == "":
// Not installed yet — create it explicitly in the shared schema.
if _, err := conn.ExecContext(ctx, fmt.Sprintf(
"CREATE EXTENSION IF NOT EXISTS %s SCHEMA %s",
pq.QuoteIdentifier(ext), pq.QuoteIdentifier(sharedSchema),
)); err != nil {
return fmt.Errorf(
"failed to create extension %q in schema %q (a privileged user must run "+
"CREATE EXTENSION %s SCHEMA %s once): %w",
ext, sharedSchema, ext, sharedSchema, err,
)
}
return nil
case schema != sharedSchema:
// Installed, but somewhere this tenant's search_path will not reach. Fail
// with an actionable message rather than letting migrations die on a
// confusing "type does not exist".
return fmt.Errorf(
"extension %q is installed in schema %q, but multi-tenant mode requires it in %q "+
"so every tenant can reach it; either run ALTER EXTENSION %s SET SCHEMA %s, "+
"or set DATABASE_EXTENSIONS_SCHEMA=%s to match where it already lives",
ext, schema, sharedSchema, ext, sharedSchema, schema,
)
default:
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 eView on GitHub (pinned to ea665308ba)
Solutions
- Move the extension into the expected schema: ALTER EXTENSION vector SET SCHEMA <shared>; (repeat for pg_trgm).
- Or set DATABASE_EXTENSIONS_SCHEMA=<actual-schema> in .env/docker-compose to match where the extension already lives.
- Verify with: SELECT e.extname, n.nspname FROM pg_extension e JOIN pg_namespace n ON n.oid=e.extnamespace;
- Keep DATABASE_EXTENSIONS_SCHEMA consistent across all instances sharing the database.
Example fix
// before # .env # DATABASE_EXTENSIONS_SCHEMA unset; vector lives in 'extensions' // after # .env DATABASE_EXTENSIONS_SCHEMA=extensions -- or run: ALTER EXTENSION vector SET SCHEMA public;
Defensive patterns
Strategy: validation
Validate before calling
-- confirm where each extension actually lives before choosing DATABASE_EXTENSIONS_SCHEMA
SELECT e.extname, n.nspname
FROM pg_extension e JOIN pg_namespace n ON n.oid = e.extnamespace
WHERE e.extname IN ('vector','pg_trgm'); Try / catch
if err := EnsureTenantSchema(ctx, cfg); err != nil {
var schema, expected string
if _, scanErr := fmt.Sscanf(err.Error(), "extension %q is installed in schema %q", new(interface{}), &schema); scanErr == nil {
log.Error().Msgf("set DATABASE_EXTENSIONS_SCHEMA=%s or ALTER EXTENSION SET SCHEMA", schema)
}
return err
} Prevention
- Set DATABASE_EXTENSIONS_SCHEMA explicitly in .env rather than relying on defaults
- Keep it identical across every instance sharing the database
- Include the pg_extension/pg_namespace query in deployment smoke tests
- Document the chosen extension schema in runbooks next to DATABASE_URL
When it happens
Trigger: TENANT_ID is set, pg_extension shows e.g. vector installed in schema 'extensions' (or 'public'), but cfg.ExtensionSchema() expects a different schema — typically because DATABASE_EXTENSIONS_SCHEMA is unset/defaulted while an admin pre-installed extensions elsewhere, or vice versa.
Common situations: Ops installed pgvector into a custom schema but .env omits DATABASE_EXTENSIONS_SCHEMA; migrating from single-tenant (extensions in public) to multi-tenant with a custom extension schema; DBA policy moving extensions out of public; mismatch between docker-compose env and docs config.
Related errors
- failed to create schema %q: %w
- failed to create extension %q in schema %q (a privileged use
- search_path resolved to schema %q, expected %q — refusing to
- knowledge: list by flow: %w
- knowledge: list all: %w
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/e1fae2abb4e434d1.
Report an issue: GitHub.