immich-app/immich · error
extension is not installed
Error message
${EXTENSION_NAMES[extension]} extension is not installed What it means
updateVectorExtension upgrades a vector extension to targetVersion, but first checks the currently installed version via getExtensionVersions. If the extension is not installed in this database (installedVersion is empty), it throws instead of silently proceeding. Note this method updates an existing extension; installing a fresh one is a different code path.
Solutions
- Install the extension first: CREATE EXTENSION IF NOT EXISTS vector; (or 'vectors'/'vchord') then retry the update
- Confirm you are connected to the Immich database (check DB_DATABASE_NAME) — the extension may be installed in a different database
- Check installed extensions with SELECT extname FROM pg_extension; and use the exact name Immich expects
- If the extension was intentionally removed, use the install path (e.g. Immich's createVectorExtension) instead of the update path
Example fix
-- before running the app/upgrade DROP EXTENSION IF EXISTS vector; -- after CREATE EXTENSION IF NOT EXISTS vector;
Defensive patterns
Strategy: validation
Validate before calling
const { rows } = await sql`SELECT extname FROM pg_extension WHERE extname IN ('vector','vectors','vchord')`;
if (!rows.some((r) => r.extname === 'vector')) await sql`CREATE EXTENSION IF NOT EXISTS vector`; Type guard
function isInstalled(versions: { name: string; installedVersion: string | null }[]): boolean {
return versions.length > 0 && versions[0].installedVersion != null;
} Try / catch
try {
await repo.updateVectorExtension(extension);
} catch (e) {
if ((e as Error).message.endsWith('extension is not installed')) {
await sql`CREATE EXTENSION IF NOT EXISTS vector`; // install then retry once
} else throw e;
} Prevention
- Run CREATE EXTENSION IF NOT EXISTS as part of initial provisioning
- Verify connection targets the correct database before extension operations
- Check pg_extension contents in pre-deploy health checks
When it happens
Trigger: Calling updateVectorExtension('vector', ...) when the CREATE EXTENSION for that extension was never run in the connected database, or it was dropped (DROP EXTENSION) beforehand.
Common situations: Running migration/upgrade tooling against a fresh database that never had the extension; the extension was dropped during a failed migration; connecting to the wrong database/schema where the extension is absent; hand-running DROP EXTENSION during a manual cleanup.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- Migration " " failed
- No available version for
- Table does not exist, skipping reindexing. This is only…
- The database currently has
- Unsupported vector extension
AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15).
Data as JSON: /api/errors/283374380f475029.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/repositories/database.repository.ts:131
async createExtension(extension: DatabaseExtension): Promise<void> {
this.logger.log(`Creating ${EXTENSION_NAMES[extension]} extension`);
await sql`CREATE EXTENSION IF NOT EXISTS ${sql.raw(extension)} CASCADE`.execute(this.db);
if (extension === DatabaseExtension.VectorChord) {
const dbName = sql.id(await this.getDatabaseName());
await sql`ALTER DATABASE ${dbName} SET vchordrq.probes = 1`.execute(this.db);
await sql`SET vchordrq.probes = 1`.execute(this.db);
}
}
async dropExtension(extension: DatabaseExtension): Promise<void> {
this.logger.log(`Dropping ${EXTENSION_NAMES[extension]} extension`);
await sql`DROP EXTENSION IF EXISTS ${sql.raw(extension)}`.execute(this.db);
}
async updateVectorExtension(extension: VectorExtension, targetVersion?: string): Promise<void> {
const [{ availableVersion, installedVersion }] = await this.getExtensionVersions([extension]);
if (!installedVersion) {
throw new Error(`${EXTENSION_NAMES[extension]} extension is not installed`);
}
if (!availableVersion) {
throw new Error(`No available version for ${EXTENSION_NAMES[extension]} extension`);
}
targetVersion ??= availableVersion;
if (!diff(installedVersion, targetVersion)) {
return;
}
await Promise.all([
this.db.schema.dropIndex(VectorIndex.Clip).ifExists().execute(),
this.db.schema.dropIndex(VectorIndex.Face).ifExists().execute(),
]);
await sql`ALTER EXTENSION ${sql.raw(extension)} UPDATE TO ${sql.lit(targetVersion)}`.execute(this.db);
await Promise.all([this.reindexVectors(VectorIndex.Clip), this.reindexVectors(VectorIndex.Face)]);View on GitHub (pinned to e55ac299a4)