{"record":{"id":"4ed483a2ab5f3f64","repo":"vxcontrol/pentagi","slug":"failed-to-create-extension-q-in-schema-q-a-priv","errorCode":null,"errorMessage":"failed to create extension %q in schema %q (a privileged user must run CREATE EXTENSION %s SCHEMA %s once): %w","messagePattern":"failed to create extension %q in schema %q \\(a privileged user must run CREATE EXTENSION (.+?) SCHEMA (.+?) once\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/database/tenant.go","lineNumber":117,"sourceCode":"// ensureSharedExtension guarantees that ext exists in sharedSchema and is\n// therefore reachable from every tenant's search_path. It checks before\n// creating so that a database whose extensions were pre-installed by an\n// administrator (or by convention — see DATABASE_EXTENSIONS_SCHEMA in\n// backend/docs/config.md) works without the application needing CREATE\n// privileges.\nfunc ensureSharedExtension(ctx context.Context, conn *sql.Conn, ext, sharedSchema string) error {\n\tschema, err := extensionSchema(ctx, conn, ext)\n\tswitch {\n\tcase err != nil:\n\t\treturn err\n\n\tcase schema == \"\":\n\t\t// Not installed yet — create it explicitly in the shared schema.\n\t\tif _, err := conn.ExecContext(ctx, fmt.Sprintf(\n\t\t\t\"CREATE EXTENSION IF NOT EXISTS %s SCHEMA %s\",\n\t\t\tpq.QuoteIdentifier(ext), pq.QuoteIdentifier(sharedSchema),\n\t\t)); err != nil {\n\t\t\treturn fmt.Errorf(\n\t\t\t\t\"failed to create extension %q in schema %q (a privileged user must run \"+\n\t\t\t\t\t\"CREATE EXTENSION %s SCHEMA %s once): %w\",\n\t\t\t\text, sharedSchema, ext, sharedSchema, err,\n\t\t\t)\n\t\t}\n\t\treturn nil\n\n\tcase schema != sharedSchema:\n\t\t// Installed, but somewhere this tenant's search_path will not reach. Fail\n\t\t// with an actionable message rather than letting migrations die on a\n\t\t// confusing \"type does not exist\".\n\t\treturn fmt.Errorf(\n\t\t\t\"extension %q is installed in schema %q, but multi-tenant mode requires it in %q \"+\n\t\t\t\t\"so every tenant can reach it; either run ALTER EXTENSION %s SET SCHEMA %s, \"+\n\t\t\t\t\"or set DATABASE_EXTENSIONS_SCHEMA=%s to match where it already lives\",\n\t\t\text, schema, sharedSchema, ext, sharedSchema, schema,\n\t\t)\n","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/database/tenant.go#L99-L135","documentation":"ensureSharedExtension found that a required extension (vector, pg_trgm) is not installed anywhere and attempted CREATE EXTENSION IF NOT EXISTS <ext> SCHEMA <shared> on the bootstrap connection. PostgreSQL raises an error when the connecting role lacks superuser/CREATEDB-appropriate privileges or the extension's control file is missing. The message explicitly says a privileged user must run the CREATE EXTENSION once because the app intentionally supports pre-installation by an administrator.","triggerScenarios":"TENANT_ID is set, extensionSchema() returns \"\" for \"vector\" or \"pg_trgm\", and the CREATE EXTENSION fails: role is not superuser and lacks the extension's creation rights, or the extension .control/.so files are not installed in the PostgreSQL image (e.g. plain postgres image without pgvector).","commonSituations":"Using the stock postgres Docker image instead of pgvector/pgvector:pg16, so pgvector is not available at all; running PentAGI with a non-superuser application role; upgrading the DB image and losing the pgvector package; managed databases (RDS/Cloud SQL) where CREATE EXTENSION requires specific whitelisting.","solutions":["Install the extension into the image: use the pgvector/pgvector image or apt-get install postgresql-16-pgvector / pg_trgm package, then restart.","Run once as a superuser: CREATE EXTENSION vector SCHEMA public; CREATE EXTENSION pg_trgm SCHEMA public; (use your DATABASE_EXTENSIONS_SCHEMA).","On managed Postgres, enable pgvector/pg_trgm for the instance via the provider's supported-extensions list and use a role allowed to create it.","If extensions are pre-installed by ops, just make sure they exist in the shared schema so the app skips creation (schema != \"\" path)."],"exampleFix":"// before (app role)\nCREATE EXTENSION IF NOT EXISTS vector SCHEMA public; -- ERROR: permission denied to create extension\n// after (run once as postgres superuser)\nCREATE EXTENSION IF NOT EXISTS vector SCHEMA public;\nCREATE EXTENSION IF NOT EXISTS pg_trgm SCHEMA public;","handlingStrategy":"validation","validationCode":"// verify extension availability before app start\npsql \"$DATABASE_URL\" -c \"SELECT name FROM pg_available_extensions WHERE name IN ('vector','pg_trgm');\"\n// empty result means the image lacks the extension packages","typeGuard":null,"tryCatchPattern":"if err := EnsureTenantSchema(ctx, cfg); err != nil {\n    if strings.Contains(err.Error(), \"failed to create extension\") {\n        return fmt.Errorf(\"install pgvector/pg_trgm in the image and run CREATE EXTENSION once as superuser: %w\", err)\n    }\n    return err\n}","preventionTips":["Use the pgvector/pgvector image (or install postgresql-<v>-pgvector) instead of stock postgres","Pre-install extensions as admin so the app never needs CREATE privileges","On managed Postgres, whitelist pgvector/pg_trgm before deploying","Pin the DB image version in docker-compose.yml"],"tags":["postgres","pgvector","extension","permissions","docker"],"backgroundTag":"create-extension-permission-denied","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}