{"record":{"id":"6a99043e80d33ef2","repo":"immich-app/immich","slug":"migration-missing-1-was-already-applied-to-t","errorCode":null,"errorMessage":"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.","messagePattern":"Migration \"(.+?)\" was already applied to this database but is not in this version of Immich \\((.+?)\\)\\. This usually means the database was migrated by a newer version\\. Downgrades are not supported\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"server/src/repositories/database.repository.ts","lineNumber":402,"sourceCode":"    const migrator = this.createMigrator();\n\n    const { error, results = [] } = await migrator.migrateToLatest();\n\n    for (const result of results) {\n      if (result.status === 'Success') {\n        this.logger.log(`Migration \"${result.migrationName}\" succeeded`);\n      } else if (result.status === 'Error') {\n        this.logger.warn(`Migration \"${result.migrationName}\" failed`);\n      }\n    }\n\n    if (error) {\n      this.logger.error(`Migrations failed: ${error}`);\n\n      const missing =\n        error instanceof Error ? error.message.match(/previously executed migration (.+) is missing/u) : null;\n      if (missing) {\n        throw new Error(\n          `Migration \"${missing[1]}\" was already applied to this database but is not in this version of Immich (${serverVersion}). ` +\n            `This usually means the database was migrated by a newer version. Downgrades are not supported.`,\n          { cause: error },\n        );\n      }\n\n      throw error;\n    }\n\n    this.logger.log('Finished running migrations');\n    return results.length;\n  }\n\n  async migrateFilePaths(sourceFolder: string, targetFolder: string): Promise<void> {\n    // remove trailing slashes\n    if (sourceFolder.endsWith('/')) {\n      sourceFolder = sourceFolder.slice(0, -1);\n    }","sourceCodeStart":384,"sourceCodeEnd":420,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/repositories/database.repository.ts#L384-L420","documentation":"After a failed migration run, Immich inspects the error for the Kysely 'previously executed migration ... is missing' signature. That means the migrations table records migrations that don't exist in this Immich version's migration set — i.e. the database was migrated by a NEWER Immich build, and downgrading is unsupported. Immich rethrows with a human-friendly explanation including the offending migration name and server version.","triggerScenarios":"Starting an older Immich version against a database whose migrations table contains migrations from a newer Immich build (e.g. rolling back a container tag from v1.x to v1.(x-1)).","commonSituations":"Pinning/rolling back the Immich Docker image after a newer version already ran migrations; restoring an old app container against a newer database volume; alternate deployments (e.g. a test instance) sharing the database.","solutions":["Restore the newer Immich version that created those migrations (roll the image tag back forward)","Restore a database backup taken before the newer version ran its migrations, then run the older version","Never downgrade Immich across DB migrations; check the migrations table (select * from migrations order by name desc;) to confirm the offending entry","If a single bad record is blocking intentionally and you accept data risk, only as a last resort align the migrations table with the old version's migration set — unsupported and likely to corrupt schema state"],"exampleFix":"// before (docker-compose.yml)\nimage: ghcr.io/immich-app/immich-server:v1.118.0\n// after — return to the version that migrated the DB\nimage: ghcr.io/immich-app/immich-server:v1.122.0","handlingStrategy":"try-catch","validationCode":"const applied = await sql`SELECT name FROM migrations`;\nconst known = new Set(allMigrations.map((m) => m.name));\nconst unknown = applied.filter((r) => !known.has(r.name));\nif (unknown.length > 0) throw new Error(`DB has migrations from a newer version: ${unknown.map((u) => u.name).join(', ')}`);","typeGuard":null,"tryCatchPattern":"try {\n  await repo.runMigrations(force);\n} catch (e) {\n  if ((e as Error).message.includes('Downgrades are not supported')) {\n    logger.fatal('Deploy the newer Immich version or restore a pre-migration DB backup; aborting startup.');\n    process.exit(1);\n  }\n  throw e;\n}","preventionTips":["Never roll back the Immich image after a newer version migrated the DB","Snapshot the database before upgrades so you can restore instead of downgrading","Keep server and ML/web image tags in lockstep and pin them explicitly"],"tags":["migration","database","versioning","downgrade"],"backgroundTag":"invalid-state-transition","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"}