immich-app/immich · warning

Could not retrieve dimension size of column

Error message

Could not retrieve dimension size of column '${column}' in table '${table}', assuming 512

What it means

getDimensionSize reads the embedding column's dimension from the database (e.g. via pgvector's typmod or a constraint). If the value cannot be retrieved or fails validation (must be an integer 1..65536), the code logs this warning and assumes a dimension of 512. A wrong assumption here can cause dimension mismatches during embedding operations.

Solutions

  1. Run migrations and the vector-extension reindex flow so the embedding column has the proper dim_size_constraint
  2. Check the constraint: SELECT conname, pg_get_constraintdef(oid) FROM pg_constraint WHERE conrelid = 'smart_search'::regclass;
  3. Set the dimension explicitly via the admin settings (which calls setDimensionSize) matching your CLIP model (512 for ViT-B-32)
  4. Verify pgvector extension is installed: CREATE EXTENSION IF NOT EXISTS vectors;

Example fix

// before (column without dimension)
embedding real[]
// after
ALTER TABLE smart_search ADD CONSTRAINT dim_size_constraint CHECK (array_length(embedding::real[], 1) = 512);
-- or let migrations define embedding vector(512)
Defensive patterns

Strategy: fallback

Validate before calling

const { rows } = await sql`
  SELECT atttypmod AS dim FROM pg_attribute
  WHERE attrelid = 'smart_search'::regclass AND attname = 'embedding'`.execute(db);
const dim = Number(rows[0]?.dim);
if (!Number.isInteger(dim) || dim < 1 || dim > 65536) {
  throw new Error('Embedding dimension unknown — run migrations / set vector dimension explicitly');
}

Type guard

function isValidDim(v: unknown): v is number {
  return typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= 65536;
}

Try / catch

try {
  const dim = await db.getDimensionSize('smart_search', 'embedding');
  assert(dim === expectedModelDim, `dimension ${dim} != model dim ${expectedModelDim}`);
} catch (err) {
  logger.error('Dimension unavailable or mismatched; do not embed until fixed');
}

Prevention

When it happens

Trigger: Querying the dimension of a column in smart_search/face_search returns null, or a value outside 1..2**16 — e.g. the embedding column is still real[] without a dim constraint, or the pgvector column attribute could not be parsed.

Common situations: Fresh table where embedding was added as plain real[] (see reindex path); migrations not fully applied; querying a non-vector column; broken pgvector installation.

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


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

Appendix: source

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

    const { rows } = await sql<{ dimsize: number }>`
      SELECT atttypmod as dimsize
      FROM pg_attribute f
        JOIN pg_class c ON c.oid = f.attrelid
      WHERE c.relkind = 'r'::char
        AND f.attnum > 0
        AND c.relname = ${table}::text
        AND f.attname = ${column}::text
    `.execute(this.db);

    const dimSize = rows[0]?.dimsize;
    if (
      !z
        .int()
        .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) => {

View on GitHub (pinned to e55ac299a4)