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 e

View on GitHub (pinned to ea665308ba)

Solutions

  1. Move the extension into the expected schema: ALTER EXTENSION vector SET SCHEMA <shared>; (repeat for pg_trgm).
  2. Or set DATABASE_EXTENSIONS_SCHEMA=<actual-schema> in .env/docker-compose to match where the extension already lives.
  3. Verify with: SELECT e.extname, n.nspname FROM pg_extension e JOIN pg_namespace n ON n.oid=e.extnamespace;
  4. 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

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


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