{"record":{"id":"40f354dbf7d2145e","repo":"immich-app/immich","slug":"column-embedding-does-not-exist-in-table-table-truncating","errorCode":null,"errorMessage":"Column 'embedding' does not exist in table '${table}', truncating and adding column.","messagePattern":"Column 'embedding' does not exist in table '(.+?)', truncating and adding column\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/src/repositories/database.repository.ts","lineNumber":235,"sourceCode":"\n    const { rows } = await sql<{\n      columnName: string;\n    }>`SELECT column_name as \"columnName\" FROM information_schema.columns WHERE table_name = ${table}`.execute(this.db);\n    if (rows.length === 0) {\n      this.logger.warn(\n        `Table ${table} does not exist, skipping reindexing. This is only normal if this is a new Immich instance.`,\n      );\n      return;\n    }\n    const dimSize = await this.getDimensionSize(table);\n    lists ||= this.targetListCount(await this.getRowCount(table));\n    await this.db.transaction().execute(async (tx) => {\n      await sql`DROP INDEX IF EXISTS ${sql.raw(indexName)}`.execute(tx);\n      if (table === 'smart_search') {\n        await sql`ALTER TABLE ${sql.raw(table)} DROP CONSTRAINT IF EXISTS dim_size_constraint`.execute(tx);\n      }\n      if (rows.every((row) => row.columnName !== 'embedding')) {\n        this.logger.warn(`Column 'embedding' does not exist in table '${table}', truncating and adding column.`);\n        await sql`TRUNCATE TABLE ${sql.raw(table)}`.execute(tx);\n        await sql`ALTER TABLE ${sql.raw(table)} ADD COLUMN embedding real[] NOT NULL`.execute(tx);\n      }\n      await sql`ALTER TABLE ${sql.raw(table)} ALTER COLUMN embedding SET DATA TYPE real[]`.execute(tx);\n      await sql`\n        ALTER TABLE ${sql.raw(table)}\n        ALTER COLUMN embedding\n        SET DATA TYPE vector(${sql.raw(String(dimSize))})`.execute(tx);\n      await sql.raw(vectorIndexQuery({ vectorExtension, table, indexName, lists })).execute(tx);\n    });\n    this.logger.log(`Reindexed ${indexName}`);\n    void this.vacuum({ table }).catch((error) => this.logger.warn(`Failed to vacuum ${table}: ${error}`));\n  }\n\n  async vacuum({ analyze = false, table }: { analyze?: boolean; table?: keyof DB } = {}): Promise<void> {\n    try {\n      await sql`VACUUM ${sql.raw(analyze ? 'ANALYZE' : '')} ${sql.raw(table ?? '')}`.execute(this.db);\n    } catch (error) {","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/repositories/database.repository.ts#L217-L253","documentation":"While reindexing a vector table, if the expected 'embedding' column is missing, the code truncates the table and recreates the column as real[]. All existing embeddings in that table are destroyed. This indicates schema drift: the table exists but its embedding column does not.","triggerScenarios":"reindexVectors (via updateVectorExtension or reindexVectorsIfNeeded) runs against a table where every information_schema row shows no column named 'embedding' — e.g. a partially applied migration or an old schema.","commonSituations":"Interrupted or failed migrations leaving the table without the embedding column; manual schema edits; restoring a partial dump; switching vector extensions against a legacy table layout.","solutions":["Re-run Immich so migrations complete, then trigger reindexing via the admin settings (vector extension update)","Back up the database before reindexing since embeddings will be re-generated (smart search / facial recognition will rebuild)","If the data is expendable, accept the TRUNCATE and let Immich re-embed the library","Check migration history (migrations table) for failed migrations and fix them before reindexing"],"exampleFix":"// before (partial schema)\nALTER TABLE smart_search ADD COLUMN embedding vector(512); // applied without full migration\n// after (let migrations + reindex rebuild)\n-- ensure migrations succeeded, then in Immich admin: Update vector extension, which drops/recreates the index correctly","handlingStrategy":"fallback","validationCode":"const hasEmbedding = await db\n  .selectFrom('information_schema.columns')\n  .where('table_name', '=', table)\n  .where('column_name', '=', 'embedding')\n  .select(({ fn }) => fn.countAll().as('n'))\n  .executeTakeFirst();\nif (!hasEmbedding || Number(hasEmbedding.n) === 0) {\n  throw new Error(`Refusing reindex: ${table} lacks 'embedding' column — run migrations first`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await backupDatabase();\n  await db.reindexVectorsIfNeeded();\n} catch (err) {\n  logger.error('Reindex failed; restore from backup if schema is inconsistent');\n  throw err;\n}","preventionTips":["Back up the database (esp. embeddings) before upgrading Immich","Never edit embedding columns manually; let migrations manage them","Ensure previous migrations succeeded before triggering reindex","Monitor migration logs after every version upgrade"],"tags":["database","postgres","schema-migration","vector-index"],"backgroundTag":"schema-validation-failed","analyzedSha":"e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}