immich-app/immich · error

Invalid backup file format!

Error message

Invalid backup file format!

What it means

restoreDatabaseBackup refuses to restore a file whose name does not pass isValidDatabaseBackupName, throwing before any filesystem or database work. This guards against restoring arbitrary/attacker-controlled paths. The raw Error is caught in the method's try/catch and triggers a rollback of the restore.

Solutions

  1. Restore only files that exist in the server's Backups storage folder with the original Immich-generated name (immich-dbBackup-*.sql.gz).
  2. Rename the file back to its original backup name before requesting restore.
  3. Verify the name with the same pattern locally: /^immich-dbBackup-.*\.sql\.gz$/ (or list backups via API and use returned names).

Example fix

// before
await api.restoreDatabaseBackup('my-dump.sql.gz');
// after
await api.restoreDatabaseBackup('immich-dbBackup-1700000000000.sql.gz');
Defensive patterns

Strategy: validation

Validate before calling

const BACKUP_NAME_RE = /^immich-dbBackup-.*\.sql\.gz$/;
if (!BACKUP_NAME_RE.test(filename)) throw new Error('Not a valid Immich backup file name');

Try / catch

try {
  await api.restoreDatabaseBackup(filename);
} catch (e) {
  if (/Invalid backup file format/.test(e.message)) {
    console.error('Use a server-side backup file with its original name:', filename);
  } else throw e;
}

Prevention

When it happens

Trigger: POSTing a restore request with a filename that does not match the Immich database backup naming pattern (e.g. uploaded file renamed, or a path like '../../dump.sql').

Common situations: Users renaming .sql.gz dumps before upload; selecting the wrong file from the backups folder; crafted filenames for path traversal.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15). Data as JSON: /api/errors/0f6358324769b132. Report an issue: GitHub.

Appendix: source

Thrown at server/src/services/database-backup.service.ts:370

    toDelete.push(...failedBackups);

    for (const file of toDelete) {
      await this.storageRepository.unlink(path.join(backupsFolder, file));
    }

    this.logger.debug(`Database Backup Cleanup Finished, deleted ${toDelete.length} backups`);
  }

  async restoreDatabaseBackup(
    filename: string,
    progressCb?: (action: 'backup' | 'restore' | 'migrations' | 'rollback', progress: number) => void,
  ): Promise<void> {
    this.logger.debug(`Database Restore Started`);

    let isComplete = false;
    try {
      if (!isValidDatabaseBackupName(filename)) {
        throw new Error('Invalid backup file format!');
      }

      const backupFilePath = path.join(StorageCore.getBaseFolder(StorageFolder.Backups), filename);
      await this.storageRepository.stat(backupFilePath); // => check file exists

      let isPgClusterDump = false;
      const version = findDatabaseBackupVersion(filename);
      if (version && satisfies(version, '<= 2.4')) {
        isPgClusterDump = true;
      }

      const { bin, args, databaseUsername, databasePassword, databaseMajorVersion } =
        await this.buildPostgresLaunchArguments('psql', {
          singleTransaction: !isPgClusterDump,
        });

      progressCb?.('backup', 0.05);

View on GitHub (pinned to e55ac299a4)