immich-app/immich · error · Error

Invalid CLIP dimension size: ${dimSize}

Error message

Invalid CLIP dimension size: ${dimSize}

What it means

setDimensionSize(dimSize) validates dimSize with z.int().min(1).max(2**16) (i.e. an integer in [1, 65536]). Any non-integer, <=0, >65536, or non-numeric value throws Error('Invalid CLIP dimension size: <dimSize>'). The dimension size drives the vector(N) column type on smart_search.embedding.

Source

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

        .min(1)
        .max(2 ** 16)
        .safeParse(dimSize).success
    ) {
      this.logger.warn(`Could not retrieve dimension size of column '${column}' in table '${table}', assuming 512`);
      return 512;
    }
    return dimSize;
  }

  async setDimensionSize(dimSize: number): Promise<void> {
    if (
      !z
        .int()
        .min(1)
        .max(2 ** 16)
        .safeParse(dimSize).success
    ) {
      throw new Error(`Invalid CLIP dimension size: ${dimSize}`);
    }

    // this is done in two transactions to handle concurrent writes
    await this.db.transaction().execute(async (trx) => {
      await sql`delete from ${sql.table('smart_search')}`.execute(trx);
      await trx.schema.alterTable('smart_search').dropConstraint('dim_size_constraint').ifExists().execute();
      await sql`alter table ${sql.table('smart_search')} add constraint dim_size_constraint check (array_length(embedding::real[], 1) = ${sql.lit(dimSize)})`.execute(
        trx,
      );
    });

    const vectorExtension = await this.getVectorExtension();
    await this.db.transaction().execute(async (trx) => {
      await sql`drop index if exists clip_index`.execute(trx);
      await trx.schema
        .alterTable('smart_search')
        .alterColumn('embedding', (col) => col.setDataType(sql.raw(`vector(${dimSize})`)))
        .execute();

View on GitHub (pinned to 199723261c)

Solutions

  1. Pass a positive integer between 1 and 65536 matching your CLIP model embedding dimension.
  2. Confirm the model true output dimension from its spec before applying.
  3. Ensure the value is typed as a number, not a string, at the call site.

Example fix

// before
await repo.setDimensionSize(768.5);
// after
await repo.setDimensionSize(768);
Defensive patterns

Strategy: validation

Validate before calling

import { z } from 'zod';
const Dim = z.int().min(1).max(2 ** 16);
const r = Dim.safeParse(dimSize);
if (!r.success) throw new Error(`Invalid CLIP dimension size: ${dimSize}`);

Type guard

const isValidDim = (n: number): boolean =>
  Number.isInteger(n) && n >= 1 && n <= 2 ** 16;

Prevention

When it happens

Trigger: Calling setDimensionSize (via the admin API that exposes it) with a fractional, zero, negative, >65536, or non-numeric CLIP dimension value.

Common situations: Configuring a custom CLIP model whose embedding dimension is mistyped; passing a string instead of a number; choosing a dimension larger than pgvector supported max.

Related errors


AI-assisted analysis of immich-app/immich@199723261c (2026-08-12). Data as JSON: /api/errors/fa8d74940bb23a1a. Report an issue: GitHub.