{"record":{"id":"fa8d74940bb23a1a","repo":"immich-app/immich","slug":"invalid-clip-dimension-size-dimsize","errorCode":null,"errorMessage":"Invalid CLIP dimension size: ${dimSize}","messagePattern":"Invalid CLIP dimension size: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/src/repositories/database.repository.ts","lineNumber":316,"sourceCode":"        .min(1)\n        .max(2 ** 16)\n        .safeParse(dimSize).success\n    ) {\n      this.logger.warn(`Could not retrieve dimension size of column '${column}' in table '${table}', assuming 512`);\n      return 512;\n    }\n    return dimSize;\n  }\n\n  async setDimensionSize(dimSize: number): Promise<void> {\n    if (\n      !z\n        .int()\n        .min(1)\n        .max(2 ** 16)\n        .safeParse(dimSize).success\n    ) {\n      throw new Error(`Invalid CLIP dimension size: ${dimSize}`);\n    }\n\n    // this is done in two transactions to handle concurrent writes\n    await this.db.transaction().execute(async (trx) => {\n      await sql`delete from ${sql.table('smart_search')}`.execute(trx);\n      await trx.schema.alterTable('smart_search').dropConstraint('dim_size_constraint').ifExists().execute();\n      await sql`alter table ${sql.table('smart_search')} add constraint dim_size_constraint check (array_length(embedding::real[], 1) = ${sql.lit(dimSize)})`.execute(\n        trx,\n      );\n    });\n\n    const vectorExtension = await this.getVectorExtension();\n    await this.db.transaction().execute(async (trx) => {\n      await sql`drop index if exists clip_index`.execute(trx);\n      await trx.schema\n        .alterTable('smart_search')\n        .alterColumn('embedding', (col) => col.setDataType(sql.raw(`vector(${dimSize})`)))\n        .execute();","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/immich-app/immich/blob/199723261c6ffa897fec8ccdaea6359e39c37cc3/server/src/repositories/database.repository.ts#L298-L334","documentation":"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.","triggerScenarios":"Calling setDimensionSize (via the admin API that exposes it) with a fractional, zero, negative, >65536, or non-numeric CLIP dimension value.","commonSituations":"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.","solutions":["Pass a positive integer between 1 and 65536 matching your CLIP model embedding dimension.","Confirm the model true output dimension from its spec before applying.","Ensure the value is typed as a number, not a string, at the call site."],"exampleFix":"// before\nawait repo.setDimensionSize(768.5);\n// after\nawait repo.setDimensionSize(768);","handlingStrategy":"validation","validationCode":"import { z } from 'zod';\nconst Dim = z.int().min(1).max(2 ** 16);\nconst r = Dim.safeParse(dimSize);\nif (!r.success) throw new Error(`Invalid CLIP dimension size: ${dimSize}`);","typeGuard":"const isValidDim = (n: number): boolean =>\n  Number.isInteger(n) && n >= 1 && n <= 2 ** 16;","tryCatchPattern":null,"preventionTips":["Read the exact embedding dimension from the CLIP model card before setting it.","Pass numbers, not strings, to setDimensionSize.","Never exceed 65536 (pgvector limit) and never use 0/negative."],"tags":["database","machine-learning","clip","validation","vector-extension"],"backgroundTag":null,"analyzedSha":"199723261c6ffa897fec8ccdaea6359e39c37cc3","analyzedAt":"2026-08-12T04:54:27.085Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}