immich-app/immich · critical · ImmichStartupError

Failed to read: "${externalPath} (${internalPath}) - ${docsM

Error message

Failed to read: "${externalPath} (${internalPath}) - ${docsMessage}"

What it means

Thrown by Immich's StorageService.verifyReadAccess at startup when it cannot read the '.immich' mount-marker file inside a configured storage folder. The check exists so the server fails fast (ImmichStartupError) rather than silently corrupting assets on a mis-mounted volume. The message includes the external upload path, the internal resolved path, and a link to docs.immich.app/administration/system-integrity#folder-checks.

Source

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

      }

      try {
        await this.storageRepository.unlink(file);
      } catch (error: any) {
        this.logger.warn('Unable to remove file from disk', error);
      }
    }

    return JobStatus.Success;
  }

  private async verifyReadAccess(folder: StorageFolder) {
    const { internalPath, externalPath } = this.getMountFilePaths(folder);
    try {
      await this.storageRepository.readFile(internalPath);
    } catch (error) {
      this.logger.error(`Failed to read (${internalPath}): ${error}`);
      throw new ImmichStartupError(`Failed to read: "${externalPath} (${internalPath}) - ${docsMessage}"`);
    }
  }

  private async createMountFile(folder: StorageFolder) {
    const { folderPath, internalPath, externalPath } = this.getMountFilePaths(folder);
    try {
      this.storageRepository.mkdirSync(folderPath);
      await this.storageRepository.createFile(internalPath, Buffer.from(Date.now().toString()));
    } catch (error) {
      if ((error as NodeJS.ErrnoException).code === 'EEXIST') {
        this.logger.warn('Found existing mount file, skipping creation');
        return;
      }
      this.logger.error(`Failed to create ${internalPath}: ${error}`);
      throw new ImmichStartupError(`Failed to create "${externalPath} - ${docsMessage}"`);
    }
  }

View on GitHub (pinned to 199723261c)

Solutions

  1. Verify the host directory for the failing folder exists and is mounted into the container at the path shown in externalPath.
  2. Ensure the immich server process uid owns or can read the '.immich' file: chown -R <immich-uid>:<immich-gid> <UPLOAD_LOCATION>.
  3. Check the docker-compose volume mapping for the named folder matches StorageCore.getBaseFolder defaults.
  4. If using an external library, confirm the library path is accessible inside the container (docker exec ... ls).
  5. Temporarily remove IMMICH_LOG_LEVEL noise and inspect the preceding log line 'Failed to read (<internalPath>): <error>' for the OS errno.

Example fix

# before: read-only bind
volumes:
  - /mnt/photos:/usr/src/app/upload:ro
# after: read-write, correct uid
volumes:
  - /mnt/photos:/usr/src/app/upload
Defensive patterns

Strategy: validation

Validate before calling

import { access, constants } from 'node:fs/promises';
import { join } from 'node:path';

async function canReadImmichMarker(uploadRoot: string, folder: string) {
  const p = join(uploadRoot, folder, '.immich');
  try { await access(p, constants.R_OK); return true; }
  catch { return false; }
}
// run for every StorageFolder before starting the server

Try / catch

try {
  await storageService.onBootstrap(); // triggers verifyReadAccess
} catch (e) {
  if (e instanceof ImmichStartupError && e.message.startsWith('Failed to read')) {
    // surface a runbook to the operator, do not retry blindly
  }
  throw e;
}

Prevention

When it happens

Trigger: Server boot, during the per-folder access verification loop, when storageRepository.readFile(internalPath) rejects for any of the StorageFolder entries (library, upload, encoded, etc.). The thrown error stops startup.

Common situations: UPLOAD_LOCATION/bind-mount is read-only or owned by root; the folder was deleted after the container started; an external library path is not mounted into the container; NFS/CIFS mount dropped; permissions do not allow the immich process uid to read.

Related errors


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