immich-app/immich · critical

Invalid PostgreSQL version. Found

Error message

Invalid PostgreSQL version. Found ${version}, but needed ${postgresRange}. Please use a supported version.

What it means

On app bootstrap, DatabaseService reads the server's PostgreSQL version, coerces it, and checks it against the supported semver range (getPostgresVersionRange, e.g. ^14.0.0). If the version cannot be coerced or is outside the supported range, bootstrap fails hard so Immich never runs against an unsupported database.

Solutions

  1. Upgrade or downgrade the PostgreSQL server to a version inside the supported range (see getPostgresVersionRange, e.g. 14–15 for older Immich releases).
  2. Update Immich to a release that supports your Postgres version.
  3. Ensure the server actually connects to the intended Postgres instance (check DB_HOST/DB_PORT); a proxy returning a bogus version string also triggers this.

Example fix

// docker-compose.yml before
image: postgres:13
// after
image: postgres:15
Defensive patterns

Strategy: try-catch

Validate before calling

const { rows } = await db.query('SHOW server_version');
const major = parseInt(rows[0].server_version);
if (major < 14 || major > 15) console.warn('Unsupported Postgres version for this Immich release');

Try / catch

try {
  await server.start();
} catch (e) {
  if (/Invalid PostgreSQL version/.test(e.message)) {
    console.error('Switch the Postgres container to a supported version:', e.message);
  } else throw e;
}

Prevention

When it happens

Trigger: Starting the Immich server while connected to PostgreSQL 12/13/17+ (or any version outside the supported range), or when getPostgresVersion returns an unparseable value.

Common situations: Docker image with unsupported PG version; user upgraded the Postgres container past the supported range; self-hosted install pointing at an old system Postgres.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15). Data as JSON: /api/errors/bae9692cdc0f32f8. Report an issue: GitHub.

Appendix: source

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

    This may be because Immich does not have the necessary permissions to drop the extension.

    Please run 'DROP EXTENSION ${extension};' manually as a superuser.
    See https://docs.immich.app/guides/database-queries for how to query the database.`,
  invalidDowngrade: ({ name, installedVersion, availableVersion }: InvalidDowngradeArgs) =>
    `The database currently has ${name} ${installedVersion} activated, but the Postgres instance only has ${availableVersion} available.
    This most likely means the extension was downgraded.
    If ${name} ${installedVersion} is compatible with Immich, please ensure the Postgres instance has this available.`,
};

@Injectable()
export class DatabaseService extends BaseService {
  @OnEvent({ name: 'AppBootstrap', priority: BootstrapEventPriority.DatabaseService })
  async onBootstrap() {
    const version = await this.databaseRepository.getPostgresVersion();
    const current = coerce(version);
    const postgresRange = this.databaseRepository.getPostgresVersionRange();
    if (!current || !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 && eq(version, '0.0.0'))) {
        throw new Error(messages.nightlyVersion({ name, extension, version: '0.0.0' }));
      }

View on GitHub (pinned to e55ac299a4)