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
- Upgrade or downgrade the PostgreSQL server to a version inside the supported range (see getPostgresVersionRange, e.g. 14–15 for older Immich releases).
- Update Immich to a release that supports your Postgres version.
- 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
- Pin docker-compose to the Postgres image tag documented for your Immich release.
- Check Immich release notes before upgrading Postgres.
- Confirm DB_HOST/DB_PORT point at the intended instance.
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
- The extension version is , but Immich only supports …
- The database currently has
- The extension version is , which means it is a nightly…
- The extension is not available in this Postgres instance…
- Column 'embedding' does not exist in table
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)