immich-app/immich · critical · Error
Detected an inconsistent media location. For more informatio
Error message
Detected an inconsistent media location. For more information, see https://docs.immich.app/errors#inconsistent-media-location
What it means
StorageService tracks the configured media location in system metadata. On startup it compares the persisted 'previous' location with the 'current' resolved media path. If they differ AND existing repository file paths do NOT start with the previous location, it throws ErrorMessages.InconsistentMediaLocation (storage.service.ts:118, a plain Error). This protects against silently relocating media that lives in an unexpected place.
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 199723261c)
Solutions
- Follow the docs link in the message (https://docs.immich.app/errors#inconsistent-media-location) and run the official storage-location migration procedure.
- Restore the previous media path/mount so previous == current, then reboot.
- If paths are genuinely relocated, migrate file paths first (databaseRepository.migrateFilePaths) so they start with the current prefix, then restart.
- Avoid moving the upload directory by hand; use the supported migration flow.
Example fix
// before - manually moved media, DB paths stale // mv /media/photos /mnt/new/photos -> then boot -> error // after - migrate via supported flow, then boot // 1. keep/match the previous mount, OR run the official path migration, // 2. confirm stored paths start with the configured media location, then restart the server.
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight: ensure configured media location matches persisted location
// before booting the app against a moved volume.
const persisted = await systemMetadataApi.get(SystemMetadataKey.MediaLocation);
const current = resolveMediaLocation(); // your deployment's media path
if (persisted && persisted.location !== current) {
// Do NOT just boot — run the official migration first.
throw new Error(`Media location mismatch (was ${persisted.location}, now ${current}). Run the migration.`);
} Type guard
const isInconsistentMediaLocation = (e: unknown): boolean => e instanceof Error && /inconsistent media location/i.test(e.message);
Try / catch
try {
await bootstrapServer();
} catch (e) {
if (/inconsistent media location/i.test(String((e as Error).message))) {
// halt boot; surface the docs link and require operator action
failDeployment('Inconsistent media location detected. See https://docs.immich.app/errors#inconsistent-media-location and run the storage migration before restarting.');
} else throw e;
} Prevention
- Never move the upload/media directory by hand; use the supported migration flow.
- After volume/mount changes, verify stored file paths still start with the configured location before boot.
- Keep the SystemMetadata MediaLocation record consistent with the actual mount.
When it happens
Trigger: Booting the server after the upload/media directory was moved or the storageVolume mount changed, while existing DB file paths were not migrated to match — i.e. previous != current and at least one stored path does not begin with the previous prefix.
Common situations: Changing the upload volume / external library path between deploys, restoring a DB backup against a different media mount, Docker volume remapping, or moving the library folder by hand instead of via the migration tool.
Related errors
- Target media location must be an absolute path
- Failed to read: "${externalPath} (${internalPath}) - ${docsM
- Failed to create "${externalPath} - ${docsMessage}"
- Failed to write "${externalPath} - ${docsMessage}"
- Failed to read helmet file: ${helmetFile}
AI-assisted analysis of immich-app/immich@199723261c (2026-08-12).
Data as JSON: /api/errors/e0dc682901346cdb.
Report an issue: GitHub.