immich-app/immich · critical · Error

Detected an inconsistent media location. For more…

Error message

Detected an inconsistent media location. For more information, see https://docs.immich.app/errors#inconsistent-media-location

What it means

On startup (onBootstrap), Immich compares the stored previous media location with the current one; if they differ and the new external path is not a subpath of the previous one, it throws rather than attempting a migration, because an automatic path migration would be unsafe.

Solutions

  1. Restore the original mount path so data sits where Immich expects it, or make the new location a subdirectory of the old path so a migration is possible.
  2. If the move is intentional and paths aren't nested, follow the docs at https://docs.immich.app/errors#inconsistent-media-location to manually update stored paths or restore the database/volume consistently.
  3. Ensure database and uploaded files were moved together; a mismatch between DB paths and filesystem is the root cause.
  4. Use immich's provided migration tooling (migrate file paths) only when the new path starts with the old one.

Example fix

// before (docker-compose.yml)
volumes:
  - /mnt/newlibrary:/usr/src/app/upload
// after
volumes:
  - /mnt/newlibrary/upload:/usr/src/app/upload  # keeps external location consistent or nested under previous path
Defensive patterns

Strategy: try-catch

Validate before calling

// before startup, verify the configured media path is consistent with the database's stored location
const previous = await db.getSystemMetadataMediaLocation();
if (previous && !mediaPath.startsWith(previous)) throw new Error('Media location change is not a subpath; manual migration required');

Try / catch

try {
  await startImmichServer();
} catch (e) {
  if (/inconsistent media location/i.test(String(e.message))) {
    // restore original mount path or follow docs.immich.app/errors#inconsistent-media-location
    process.exit(1);
  } else throw e;
}

Prevention

When it happens

Trigger: Changing the upload/data volume mount so the new external path is not nested under the old path (e.g. from /usr/src/app/upload to /mnt/library), then starting the server.

Common situations: Docker compose volume changes; moving from a bind mount to a different host directory; renaming the host folder; container image changes that relocate the internal upload path.

Related errors


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

Appendix: source

Thrown at server/src/services/storage.service.ts:118

      const savedValue = await this.systemMetadataRepository.get(SystemMetadataKey.MediaLocation);
      if (samples.length > 0) {
        const path = samples[0].path;

        let previous = savedValue?.location || '';

        if (!previous && this.configRepository.getEnv().storage.mediaLocation) {
          previous = current;
        }

        if (!previous) {
          previous = path.startsWith('upload/') ? 'upload' : '/usr/src/app/upload';
        }

        if (previous !== current) {
          this.logger.log(`Media location changed (from=${previous}, to=${current})`);

          if (!path.startsWith(previous)) {
            throw new Error(ErrorMessages.InconsistentMediaLocation);
          }

          this.logger.warn(
            `Detected a change to media location, performing an automatic migration of file paths from ${previous} to ${current}, this may take awhile`,
          );
          await this.databaseRepository.migrateFilePaths(previous, current);
        }
      }

      // Only set MediaLocation in systemMetadataRepository if needed
      if (savedValue?.location !== current) {
        await this.systemMetadataRepository.set(SystemMetadataKey.MediaLocation, { location: current });
      }
    });
  }

  @OnJob({ name: JobName.FileDelete, queue: QueueName.BackgroundTask })
  async handleDeleteFiles(job: JobOf<JobName.FileDelete>): Promise<JobStatus> {

View on GitHub (pinned to e55ac299a4)