immich-app/immich · critical · Error

The ${name} extension version is ${version}, which mean

Error message

    The ${name} extension version is ${version}, which means it is a nightly release.

    Please run 'DROP EXTENSION IF EXISTS ${extension}' and switch to a release version.
    See https://docs.immich.app/guides/database-queries for how to query the database.

What it means

When Immich queries the vector extension version, a value of '0.0.0' signals a nightly/development build rather than a tagged release. Immich deliberately refuses nightly builds because their ABI and behavior are unstable and can corrupt vector indexes. The check fires whenever availableVersion or installedVersion equals 0.0.0 and instructs the operator to DROP and reinstall a release build.

Source

Thrown at server/src/services/database.service.ts:79

    if (!current || !semver.satisfies(current, postgresRange)) {
      throw new Error(
        `Invalid PostgreSQL version. Found ${version}, but needed ${postgresRange}. Please use a supported version.`,
      );
    }

    await this.databaseRepository.withLock(DatabaseLock.Migrations, async () => {
      const extension = await this.databaseRepository.getVectorExtension();
      const name = EXTENSION_NAMES[extension];
      const extensionRange = this.databaseRepository.getExtensionVersionRange(extension);

      const extensionVersions = await this.databaseRepository.getExtensionVersions(VECTOR_EXTENSIONS);
      const { installedVersion, availableVersion } = extensionVersions.find((v) => v.name === extension) ?? {};
      if (!availableVersion) {
        throw new Error(messages.notInstalled(name));
      }

      if ([availableVersion, installedVersion].some((version) => version && semver.eq(version, '0.0.0'))) {
        throw new Error(messages.nightlyVersion({ name, extension, version: '0.0.0' }));
      }

      if (!semver.satisfies(availableVersion, extensionRange)) {
        throw new Error(messages.outOfRange({ name, extension, version: availableVersion, range: extensionRange }));
      }

      if (!installedVersion) {
        await this.createExtension(extension);
      }

      if (installedVersion && semver.gt(availableVersion, installedVersion)) {
        await this.updateExtension(extension, availableVersion);
      } else if (installedVersion && !semver.satisfies(installedVersion, extensionRange)) {
        throw new Error(messages.outOfRange({ name, extension, version: installedVersion, range: extensionRange }));
      } else if (installedVersion && semver.lt(availableVersion, installedVersion)) {
        throw new Error(messages.invalidDowngrade({ name, extension, availableVersion, installedVersion }));
      }

View on GitHub (pinned to 199723261c)

Solutions

  1. Pin the vector extension image to a release tag (e.g. tensorchord/pgvecto-rs:pg16-v0.3.0 or a tagged pgvector image) instead of nightly.
  2. Connect to Postgres and run 'DROP EXTENSION IF EXISTS vectors;' (or 'vector') then let Immich recreate it, or recreate it manually with a release version.
  3. Confirm the release version with: SELECT extversion FROM pg_extension WHERE extname IN ('vector','vectors'); and ensure it is a non-zero semver.
  4. Restart Immich so bootstrap re-validates the extension.

Example fix

# before
image: tensorchord/pgvecto-rs:pg16-nightly
# after (pinned release)
image: tensorchord/pgvecto-rs:pg16-v0.3.0
Defensive patterns

Strategy: validation

Validate before calling

import pg from 'pg';
const client = new pg.Client({ connectionString: process.env.DB_URL });
await client.connect();
const { rows } = await client.query(
  "SELECT extname, extversion FROM pg_extension WHERE extname IN ('vector','vectors');"
);
if (rows.some((r) => r.extversion === '0.0.0' || !/\d+\.\d+\.\d+/.test(r.extversion))) {
  throw new Error('Nightly/non-release vector extension detected - install a tagged release');
}

Type guard

const isReleaseVersion = (v: string) => !!v && v !== '0.0.0' && /^\d+\.\d+\.\d+$/.test(v);

Try / catch

try {
  await app.start();
} catch (e) {
  if (/nightly release/.test(String(e?.message))) {
    // instruct operator to DROP EXTENSION and pin a release image
    logger.fatal(e.message);
    process.exit(1);
  }
  throw e;
}

Prevention

When it happens

Trigger: On bootstrap, [availableVersion, installedVersion] contains a version where semver.eq(version, '0.0.0') is true. Happens with nightly tensorchord/pgvecto.rs images, hand-compiled extensions built without a release tag, or some dev Postgres images.

Common situations: Pulling ':nightly'/'-latest' pgvecto.rs tags; building pgvector from a non-release commit; community images that report 0.0.0 as the version string.

Related errors


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