immich-app/immich · critical · Error

Migration "${missing[1]}" was already applied to this databa

Error message

Migration "${missing[1]}" was already applied to this database but is not in this version of Immich (${serverVersion}). This usually means the database was migrated by a newer version. Downgrades are not supported.

What it means

During runMigrations, if Kysely migrator errors and the message matches 'previously executed migration <name> is missing', Immich rethrows a descriptive error. That Kysely error means a migration recorded as applied in the kysely_migrations table does not exist in the code migration set — i.e. the database was migrated by a newer Immich and you are now running an older one. Immich does not support downgrades.

Source

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

    const migrator = this.createMigrator();

    const { error, results } = await migrator.migrateToLatest();

    for (const result of results ?? []) {
      if (result.status === 'Success') {
        this.logger.log(`Migration "${result.migrationName}" succeeded`);
      } else if (result.status === 'Error') {
        this.logger.warn(`Migration "${result.migrationName}" failed`);
      }
    }

    if (error) {
      this.logger.error(`Migrations failed: ${error}`);

      const missing =
        error instanceof Error ? error.message.match(/previously executed migration (.+) is missing/u) : null;
      if (missing) {
        throw new Error(
          `Migration "${missing[1]}" was already applied to this database but is not in this version of Immich (${serverVersion}). ` +
            `This usually means the database was migrated by a newer version. Downgrades are not supported.`,
          { cause: error },
        );
      }

      throw error;
    }

    this.logger.log('Finished running migrations');
  }

  async migrateFilePaths(sourceFolder: string, targetFolder: string): Promise<void> {
    // remove trailing slashes
    if (sourceFolder.endsWith('/')) {
      sourceFolder = sourceFolder.slice(0, -1);
    }

View on GitHub (pinned to 199723261c)

Solutions

  1. Run the newer Immich version that contains the listed migration (forward-only — do not try to revert the DB).
  2. If you must use the older version, restore the database from a backup made before the newer migrations were applied.
  3. Align all instances pointing at the same DB to the same (newest) Immich version.
Defensive patterns

Strategy: validation

Validate before calling

// before starting an older server, check for unknown applied migrations
const { rows } = await sql`SELECT name FROM kysely_migrations`;
const known = new Set(await readLocalMigrationNames());
const unknown = rows.filter((r) => !known.has(r.name));
if (unknown.length) throw new Error('DB has newer migrations; do not downgrade.');

Try / catch

try {
  await repo.runMigrations();
} catch (e) {
  if (/not in this version of Immich/.test((e as Error).message)) {
    // upgrade Immich to the version that migrated the DB; do not roll back
  } else throw e;
}

Prevention

When it happens

Trigger: Rolling back to an older Immich version after a newer version already applied migrations to the database; restoring a DB backup taken on a newer server into an older server.

Common situations: Downgrading Immich after an upgrade; mixing versions in a HA setup; restoring production DB into an older test instance.

Related errors


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