{"record":{"id":"bae9692cdc0f32f8","repo":"immich-app/immich","slug":"invalid-postgresql-version-found-version-but","errorCode":null,"errorMessage":"Invalid PostgreSQL version. Found ${version}, but needed ${postgresRange}. Please use a supported version.","messagePattern":"Invalid PostgreSQL version\\. Found (.+?), but needed (.+?)\\. Please use a supported version\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"server/src/services/database.service.ts","lineNumber":62,"sourceCode":"    This may be because Immich does not have the necessary permissions to drop the extension.\n\n    Please run 'DROP EXTENSION ${extension};' manually as a superuser.\n    See https://docs.immich.app/guides/database-queries for how to query the database.`,\n  invalidDowngrade: ({ name, installedVersion, availableVersion }: InvalidDowngradeArgs) =>\n    `The database currently has ${name} ${installedVersion} activated, but the Postgres instance only has ${availableVersion} available.\n    This most likely means the extension was downgraded.\n    If ${name} ${installedVersion} is compatible with Immich, please ensure the Postgres instance has this available.`,\n};\n\n@Injectable()\nexport class DatabaseService extends BaseService {\n  @OnEvent({ name: 'AppBootstrap', priority: BootstrapEventPriority.DatabaseService })\n  async onBootstrap() {\n    const version = await this.databaseRepository.getPostgresVersion();\n    const current = semver.coerce(version);\n    const postgresRange = this.databaseRepository.getPostgresVersionRange();\n    if (!current || !semver.satisfies(current, postgresRange)) {\n      throw new Error(\n        `Invalid PostgreSQL version. Found ${version}, but needed ${postgresRange}. Please use a supported version.`,\n      );\n    }\n\n    await this.databaseRepository.withLock(DatabaseLock.Migrations, async () => {\n      const extension = await this.databaseRepository.getVectorExtension();\n      const name = EXTENSION_NAMES[extension];\n      const extensionRange = this.databaseRepository.getExtensionVersionRange(extension);\n\n      const extensionVersions = await this.databaseRepository.getExtensionVersions(VECTOR_EXTENSIONS);\n      const { installedVersion, availableVersion } = extensionVersions.find((v) => v.name === extension) ?? {};\n      if (!availableVersion) {\n        throw new Error(messages.notInstalled(name));\n      }\n\n      if ([availableVersion, installedVersion].some((version) => version && semver.eq(version, '0.0.0'))) {\n        throw new Error(messages.nightlyVersion({ name, extension, version: '0.0.0' }));\n      }","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/immich-app/immich/blob/199723261c6ffa897fec8ccdaea6359e39c37cc3/server/src/services/database.service.ts#L44-L80","documentation":"Thrown (plain Error) by DatabaseService.onBootstrap at AppBootstrap. It reads the running PostgreSQL version, semver.coerce()s it, and requires it to satisfy databaseRepository.getPostgresVersionRange(). A null coerce result (unparseable version) or an out-of-range version aborts startup entirely.","triggerScenarios":"Booting the server against a PostgreSQL whose version is outside the supported range, or whose version string cannot be coerced into a semver.","commonSituations":"PG container downgraded below the minimum or upgraded past the maximum; an exotic Postgres fork (e.g. Redshift-compatible, Cockroach in PG mode) returning a non-standard version string; stale image tag pulling an unexpected major.","solutions":["Pin the PostgreSQL image to a supported major version (check getPostgresVersionRange() for the current range).","Run SELECT version(); to confirm the server reports a standard version string semver can coerce.","If migrating PG majors, follow the project's documented dump/restore upgrade path rather than just swapping the image."],"exampleFix":"// before: just start the server\nawait app.listen(port);\n\n// after: pre-flight the version before booting\nconst raw = await dbRepo.getPostgresVersion();\nconst coerced = semver.coerce(raw);\nif (!coerced || !semver.satisfies(coerced, dbRepo.getPostgresVersionRange())) {\n  throw new Error(`PostgreSQL ${raw} is unsupported; pin to the project's supported range.`);\n}\nawait app.listen(port);","handlingStrategy":"validation","validationCode":"const semver = require('semver');\nconst raw = await databaseRepository.getPostgresVersion();\nconst c = semver.coerce(raw);\nif (!c || !semver.satisfies(c, databaseRepository.getPostgresVersionRange())) {\n  throw new Error(`Unsupported PostgreSQL ${raw}; pin to the supported range.`);\n}","typeGuard":"function isSupportedVersion(raw: string | null, range: string): boolean {\n  if (!raw) return false;\n  const c = require('semver').coerce(raw);\n  return !!c && require('semver').satisfies(c, range);\n}","tryCatchPattern":null,"preventionTips":["Pin the PostgreSQL image to a supported major version.","Run SELECT version(); after upgrades to confirm a parseable version string.","Follow the documented dump/restore path when changing PG majors."],"tags":["database","postgres","bootstrap","version","startup"],"backgroundTag":null,"analyzedSha":"199723261c6ffa897fec8ccdaea6359e39c37cc3","analyzedAt":"2026-08-12T04:54:27.085Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}