immich-app/immich · critical · Error
Invalid PostgreSQL version. Found ${version}, but needed ${p
Error message
Invalid PostgreSQL version. Found ${version}, but needed ${postgresRange}. Please use a supported version. What it means
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.
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 = semver.coerce(version);
const postgresRange = this.databaseRepository.getPostgresVersionRange();
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' }));
}View on GitHub (pinned to 199723261c)
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.
Example fix
// before: just start the server
await app.listen(port);
// after: pre-flight the version before booting
const raw = await dbRepo.getPostgresVersion();
const coerced = semver.coerce(raw);
if (!coerced || !semver.satisfies(coerced, dbRepo.getPostgresVersionRange())) {
throw new Error(`PostgreSQL ${raw} is unsupported; pin to the project's supported range.`);
}
await app.listen(port); Defensive patterns
Strategy: validation
Validate before calling
const semver = require('semver');
const raw = await databaseRepository.getPostgresVersion();
const c = semver.coerce(raw);
if (!c || !semver.satisfies(c, databaseRepository.getPostgresVersionRange())) {
throw new Error(`Unsupported PostgreSQL ${raw}; pin to the supported range.`);
} Type guard
function isSupportedVersion(raw: string | null, range: string): boolean {
if (!raw) return false;
const c = require('semver').coerce(raw);
return !!c && require('semver').satisfies(c, range);
} Prevention
- 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.
When it happens
Trigger: Booting the server against a PostgreSQL whose version is outside the supported range, or whose version string cannot be coerced into a semver.
Common situations: 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.
Related errors
- The ${name} extension version is ${version}, which mean
- The ${name} extension version is ${version}, but Immich only
- The database currently has ${name} ${installedVersion} activ
- No vector extension found. Available extensions: ${VECTOR_EX
- ${EXTENSION_NAMES[extension]} extension is not installed
AI-assisted analysis of immich-app/immich@199723261c (2026-08-12).
Data as JSON: /api/errors/bae9692cdc0f32f8.
Report an issue: GitHub.