{"record":{"id":"9762cbc6cad7c875","repo":"immich-app/immich","slug":"the-name-extension-version-is-version","errorCode":null,"errorMessage":"\n    The ${name} extension version is ${version}, which means it is a nightly release.\n\n    Please run 'DROP EXTENSION IF EXISTS ${extension}' and switch to a release version.\n    See https://docs.immich.app/guides/database-queries for how to query the database.","messagePattern":"\n    The (.+?) extension version is (.+?), which means it is a nightly release\\.\n\n    Please run 'DROP EXTENSION IF EXISTS (.+?)' and switch to a release version\\.\n    See https://docs\\.immich\\.app/guides/database-queries for how to query the database\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"server/src/services/database.service.ts","lineNumber":79,"sourceCode":"    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      }\n\n      if (!semver.satisfies(availableVersion, extensionRange)) {\n        throw new Error(messages.outOfRange({ name, extension, version: availableVersion, range: extensionRange }));\n      }\n\n      if (!installedVersion) {\n        await this.createExtension(extension);\n      }\n\n      if (installedVersion && semver.gt(availableVersion, installedVersion)) {\n        await this.updateExtension(extension, availableVersion);\n      } else if (installedVersion && !semver.satisfies(installedVersion, extensionRange)) {\n        throw new Error(messages.outOfRange({ name, extension, version: installedVersion, range: extensionRange }));\n      } else if (installedVersion && semver.lt(availableVersion, installedVersion)) {\n        throw new Error(messages.invalidDowngrade({ name, extension, availableVersion, installedVersion }));\n      }\n","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/immich-app/immich/blob/199723261c6ffa897fec8ccdaea6359e39c37cc3/server/src/services/database.service.ts#L61-L97","documentation":"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.","triggerScenarios":"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.","commonSituations":"Pulling ':nightly'/'-latest' pgvecto.rs tags; building pgvector from a non-release commit; community images that report 0.0.0 as the version string.","solutions":["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.","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.","Confirm the release version with: SELECT extversion FROM pg_extension WHERE extname IN ('vector','vectors'); and ensure it is a non-zero semver.","Restart Immich so bootstrap re-validates the extension."],"exampleFix":"# before\nimage: tensorchord/pgvecto-rs:pg16-nightly\n# after (pinned release)\nimage: tensorchord/pgvecto-rs:pg16-v0.3.0","handlingStrategy":"validation","validationCode":"import pg from 'pg';\nconst client = new pg.Client({ connectionString: process.env.DB_URL });\nawait client.connect();\nconst { rows } = await client.query(\n  \"SELECT extname, extversion FROM pg_extension WHERE extname IN ('vector','vectors');\"\n);\nif (rows.some((r) => r.extversion === '0.0.0' || !/\\d+\\.\\d+\\.\\d+/.test(r.extversion))) {\n  throw new Error('Nightly/non-release vector extension detected - install a tagged release');\n}","typeGuard":"const isReleaseVersion = (v: string) => !!v && v !== '0.0.0' && /^\\d+\\.\\d+\\.\\d+$/.test(v);","tryCatchPattern":"try {\n  await app.start();\n} catch (e) {\n  if (/nightly release/.test(String(e?.message))) {\n    // instruct operator to DROP EXTENSION and pin a release image\n    logger.fatal(e.message);\n    process.exit(1);\n  }\n  throw e;\n}","preventionTips":["Pin vector extension images to release tags, never 'nightly'.","Run a pre-deploy check on pg_extension.extversion.","Keep a runbook entry for DROP EXTENSION / re-CREATE on release images."],"tags":["postgres","database","extension","version","pgvector","bootstrap","immich","config"],"backgroundTag":null,"analyzedSha":"199723261c6ffa897fec8ccdaea6359e39c37cc3","analyzedAt":"2026-08-12T04:54:27.085Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}