immich-app/immich · error
Unsupported vector extension
Error message
Unsupported vector extension: '${extension}' What it means
getExtensionVersionRange maps each known vector extension to the version range Immich supports. The default branch is reached only when a VectorExtension value outside the known set is passed, which should be impossible with valid input — it is a defensive invariant check that flags unsupported/unknown extension identifiers.
Solutions
- Ensure only vector extension enum values are passed to getExtensionVersionRange
- Add a case to the switch for the new extension returning its supported version range
- Check immich release notes for dropped/renamed extensions and update your database/extension accordingly
Example fix
// before return this.getExtensionVersionRange(DatabaseExtension.Postgres); // after return this.getExtensionVersionRange(DatabaseExtension.Vector);
Defensive patterns
Strategy: type-guard
Validate before calling
const VECTOR_EXTS = [DatabaseExtension.PgVectors, DatabaseExtension.VectorChord, DatabaseExtension.Vector] as const;
if (!VECTOR_EXTS.includes(extension as any)) throw new Error(`pass a vector extension, got ${extension}`); Type guard
function isVectorExtension(ext: DatabaseExtension): ext is DatabaseExtension.PgVectors | DatabaseExtension.VectorChord | DatabaseExtension.Vector {
return [DatabaseExtension.PgVectors, DatabaseExtension.VectorChord, DatabaseExtension.Vector].includes(ext as any);
} Try / catch
try {
range = await repo.getExtensionVersionRange(extension);
} catch (e) {
if ((e as Error).message.startsWith('Unsupported vector extension')) range = null; // skip non-vector extensions
else throw e;
} Prevention
- Keep the switch cases in sync with the DatabaseExtension enum (exhaustive switch or never-check)
- Never pass non-vector DatabaseExtension members to extension-version APIs
- Add a unit test iterating all enum members
When it happens
Trigger: Calling getExtensionVersionRange (or code paths that resolve version ranges, e.g. extension install/upgrade logic) with a DatabaseExtension value that is not pgvectors, VectorChord, or Vector — e.g. an unhandled enum member added to the extension type but not to this switch.
Common situations: A contributor adds a new DatabaseExtension enum member but forgets to add a case in the switch; internal code passing DatabaseExtension.Postgres or another non-vector enum member by mistake.
Related errors
- Column 'embedding' does not exist in table
- Could not retrieve dimension size of column
- extension is not installed
- Migration " " failed
- No available version for
AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15).
Data as JSON: /api/errors/2d367829ff24cd97.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/repositories/database.repository.ts:98
async getExtensionVersions(extensions: readonly DatabaseExtension[]): Promise<ExtensionVersion[]> {
const { rows } = await sql<ExtensionVersion>`
SELECT name, default_version as "availableVersion", installed_version as "installedVersion"
FROM pg_available_extensions
WHERE name in (${sql.join(extensions)})
`.execute(this.db);
return rows;
}
getExtensionVersionRange(extension: VectorExtension): string {
switch (extension) {
case DatabaseExtension.VectorChord: {
return VECTORCHORD_VERSION_RANGE;
}
case DatabaseExtension.Vector: {
return VECTOR_VERSION_RANGE;
}
default: {
throw new Error(`Unsupported vector extension: '${extension}'`);
}
}
}
@GenerateSql()
async getPostgresVersion(): Promise<string> {
const { rows } = await sql<{ server_version: string }>`SHOW server_version`.execute(this.db);
return rows[0].server_version;
}
getPostgresVersionRange(): string {
return POSTGRES_VERSION_RANGE;
}
async createExtension(extension: DatabaseExtension): Promise<void> {
this.logger.log(`Creating ${EXTENSION_NAMES[extension]} extension`);
await sql`CREATE EXTENSION IF NOT EXISTS ${sql.raw(extension)} CASCADE`.execute(this.db);
if (extension === DatabaseExtension.VectorChord) {View on GitHub (pinned to e55ac299a4)