immich-app/immich · warning
or run `immich-admin schema-check
Error message
${ErrorMessages.SchemaDrift} or run `immich-admin schema-check` What it means
During bootstrap, checkSchemaDrift compares the live database schema against the migrations the server expects (getSchemaDrift). If drift is detected — schema changes not produced by Immich's own migrations — the server logs this warning pointing to ErrorMessages.SchemaDrift and `immich-admin schema-check`, then lists each drifted item. The service still starts, but data integrity or future migrations may break.
Solutions
- Run `immich-admin schema-check` (or equivalent) to see the detailed drift list.
- Restore the database from a backup taken before the manual changes.
- Reconcile by reverting manual schema edits; never hand-edit Immich tables.
- Ensure server version matches the database's migration history; re-run migrations cleanly.
- If drift is understood and intentional, restore Immich-managed state before upgrading.
Example fix
// before (manual edit) ALTER TABLE assets DROP COLUMN "livePhotoVideoId"; // after (use supported API) -- do not edit schema manually; downgrade via Immich version or restore backup
Defensive patterns
Strategy: validation
Validate before calling
# before upgrading, confirm schema matches expected migrations immich-admin schema-check
Try / catch
try {
await bootstrap();
} catch (e) {
if (String(e).includes('schema')) {
console.error('Schema drift detected; restore backup or revert manual DB edits before continuing');
process.exit(1);
}
throw e;
} Prevention
- Never hand-edit the Immich database schema; use supported settings/APIs only.
- Take a database backup before every version upgrade or downgrade.
- Restore dumps only into the matching server version.
- Run schema-check as part of upgrade runbooks.
When it happens
Trigger: onBootstrap -> checkSchemaDrift finds drift.items.length > 0 from databaseRepository.getSchemaDrift().
Common situations: Database modified by hand (SQL/ORM edits); restoring a dump from a different Immich version; partially applied migrations after a crash; external tools altering tables; downgraded server against a newer schema.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- - ${warning}
- Admin account does not exist
- Album must have an owner
- Column 'embedding' does not exist in table
- Could not find asset
AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15).
Data as JSON: /api/errors/327aaef570682ca4.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/database.service.ts:137
if (migrationCount > 0) {
preparation.push(this.databaseRepository.vacuum({ analyze: true }));
}
}
preparation.push(
this.databaseRepository.prewarm(VectorIndex.Clip),
this.databaseRepository.prewarm(VectorIndex.Face),
);
await Promise.all(preparation);
});
}
private async checkSchemaDrift() {
this.logger.log('Checking for schema drift');
const drift = await this.databaseRepository.getSchemaDrift();
if (drift.items.length === 0) {
this.logger.log('No schema drift detected');
} else {
this.logger.warn(`${ErrorMessages.SchemaDrift} or run \`immich-admin schema-check\``);
for (const warning of drift.asHuman()) {
this.logger.warn(` - ${warning}`);
}
}
}
private async createExtension(extension: DatabaseExtension) {
try {
await this.databaseRepository.createExtension(extension);
} catch (error) {
const name = EXTENSION_NAMES[extension];
this.logger.fatal(messages.createFailed({ name, extension }));
throw error;
}
}
private async updateExtension(extension: VectorExtension, availableVersion: string) {
this.logger.log(`Updating ${EXTENSION_NAMES[extension]} extension to ${availableVersion}`);View on GitHub (pinned to e55ac299a4)