immich-app/immich · critical

No vector extension found. Available extensions

Error message

No vector extension found. Available extensions: ${VECTOR_EXTENSIONS.join(', ')}

What it means

Immich requires a Postgres vector extension to run vector searches. On startup, getVectorExtension queries pg_available_extensions for the supported candidates (pgvector, pgvecto.rs, VectorChord) and throws if none is installed or available in the Postgres instance. This is a hard startup blocker: without an extension, CLIP/smart-search embeddings cannot be stored or queried.

Solutions

  1. Use the Immich-provided Postgres container image (which ships pgvector/VectorChord) instead of a stock Postgres image
  2. Install a supported extension on the server: CREATE EXTENSION vector; (or vectors/pg_vectorchord after installing its files) and restart Immich
  3. Verify availability first: SELECT name FROM pg_available_extensions WHERE name IN ('vector','vectors','pg_vectorchord'); — if empty, the Postgres installation lacks the extension binaries, so install them at the OS/image level
  4. If you intentionally switched extensions, ensure the old extension's data was migrated before removing it from the server

Example fix

// before (docker-compose.yml)
image: postgres:16
// after
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0-pgvectors0.2.0
Defensive patterns

Strategy: validation

Validate before calling

const { rows } = await sql`SELECT name FROM pg_available_extensions WHERE name IN ('vector','vectors','pg_vectorchord')`.execute(runner);
if (rows.length === 0) throw new Error('Postgres image lacks a vector extension; use the immich postgres image');

Type guard

function hasVectorExtension(available: { name: string }[]): boolean {
  return ['vector', 'vectors', 'pg_vectorchord'].some((ext) => available.some((r) => r.name === ext));
}

Try / catch

try {
  await repo.getVectorExtension();
} catch (e) {
  if ((e as Error).message.startsWith('No vector extension found')) {
    // fall back to immich postgres image or install pgvector before proceeding
  }
  throw e;
}

Prevention

When it happens

Trigger: First startup against a Postgres server (including the bundled one) where none of the supported vector extensions exist in pg_available_extensions, e.g. the extensions were dropped from the image or an unsupported Postgres build is used.

Common situations: Using a plain 'postgres' Docker image instead of the Immich-provided image with pgvector/VectorChord preinstalled; running a custom Postgres build without contrib modules; upgrading Immich to a version that dropped support for a previously used extension; pg_available_extensions missing the entry because the extension files are not on the Postgres server's filesystem.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15). Data as JSON: /api/errors/bbfb304fd7f38117. Report an issue: GitHub.

Appendix: source

Thrown at server/src/repositories/database.repository.ts:49

import { vectorIndexQuery } from 'src/utils/database.js';

export let cachedVectorExtension: VectorExtension | undefined;
export async function getVectorExtension(runner: Kysely<DB>): Promise<VectorExtension> {
  if (cachedVectorExtension) {
    return cachedVectorExtension;
  }

  cachedVectorExtension = new ConfigRepository().getEnv().database.vectorExtension;
  if (cachedVectorExtension) {
    return cachedVectorExtension;
  }

  const query = `SELECT name FROM pg_available_extensions WHERE name IN (${VECTOR_EXTENSIONS.map((ext) => `'${ext}'`).join(', ')})`;
  const { rows: availableExtensions } = await sql.raw<{ name: VectorExtension }>(query).execute(runner);
  const extensionNames = new Set(availableExtensions.map((row) => row.name));
  cachedVectorExtension = VECTOR_EXTENSIONS.find((ext) => extensionNames.has(ext));
  if (!cachedVectorExtension) {
    throw new Error(`No vector extension found. Available extensions: ${VECTOR_EXTENSIONS.join(', ')}`);
  }
  return cachedVectorExtension;
}

export const probes: Record<VectorIndex, number> = {
  [VectorIndex.Clip]: 1,
  [VectorIndex.Face]: 1,
};

@Injectable()
export class DatabaseRepository {
  private readonly asyncLock = new AsyncLock();

  constructor(
    @InjectKysely() private db: Kysely<DB>,
    private logger: LoggingRepository,
    private configRepository: ConfigRepository,
  ) {

View on GitHub (pinned to e55ac299a4)