immich-app/immich · critical · Error

${EXTENSION_NAMES[extension]} extension is not installed

Error message

${EXTENSION_NAMES[extension]} extension is not installed

What it means

updateVectorExtension(extension, targetVersion?) fetches installedVersion and availableVersion for the extension. If installedVersion is null the extension is not actually installed in the DB, so it throws <Name> extension is not installed. This is distinct from the extension being available — here it is missing from the database even though an upgrade was attempted.

Source

Thrown at server/src/repositories/database.repository.ts:128

  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 (!semver.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 199723261c)

Solutions

  1. Create the extension: CREATE EXTENSION IF NOT EXISTS <extension>; in the Immich database, then restart.
  2. Verify you are connected to the correct database/schema.
  3. Re-run the startup/migration flow that calls updateVectorExtension.
Defensive patterns

Strategy: validation

Validate before calling

const res = await sql`SELECT extversion FROM pg_extension WHERE extname = '${ext}'`;
if (res.rows.length === 0) {
  throw new Error(`${ext} not installed; run CREATE EXTENSION first.`);
}

Prevention

When it happens

Trigger: Triggering a vector-extension upgrade (e.g. during a migration/startup that calls updateVectorExtension) when the extension has not been CREATE EXTENSION'd in the current database, or was dropped.

Common situations: Extension was available (so the earlier check passed) but never created in this DB; a prior dropExtension removed it; connected to a different database/schema than expected.

Related errors


AI-assisted analysis of immich-app/immich@199723261c (2026-08-12). Data as JSON: /api/errors/283374380f475029. Report an issue: GitHub.