{"record":{"id":"709b90fb818390d5","repo":"immich-app/immich","slug":"failed-to-read-externalpath-internalpath","errorCode":null,"errorMessage":"Failed to read: \"${externalPath} (${internalPath}) - ${docsMessage}\"","messagePattern":"Failed to read: \"(.+?) \\((.+?)\\) - (.+?)\"","errorType":"exception","errorClass":"ImmichStartupError","httpStatus":null,"severity":"critical","filePath":"server/src/services/storage.service.ts","lineNumber":161,"sourceCode":"      }\n\n      try {\n        await this.storageRepository.unlink(file);\n      } catch (error: any) {\n        this.logger.warn('Unable to remove file from disk', error);\n      }\n    }\n\n    return JobStatus.Success;\n  }\n\n  private async verifyReadAccess(folder: StorageFolder) {\n    const { internalPath, externalPath } = this.getMountFilePaths(folder);\n    try {\n      await this.storageRepository.readFile(internalPath);\n    } catch (error) {\n      this.logger.error(`Failed to read (${internalPath}): ${error}`);\n      throw new ImmichStartupError(`Failed to read: \"${externalPath} (${internalPath}) - ${docsMessage}\"`);\n    }\n  }\n\n  private async createMountFile(folder: StorageFolder) {\n    const { folderPath, internalPath, externalPath } = this.getMountFilePaths(folder);\n    try {\n      this.storageRepository.mkdirSync(folderPath);\n      await this.storageRepository.createFile(internalPath, Buffer.from(Date.now().toString()));\n    } catch (error) {\n      if ((error as NodeJS.ErrnoException).code === 'EEXIST') {\n        this.logger.warn('Found existing mount file, skipping creation');\n        return;\n      }\n      this.logger.error(`Failed to create ${internalPath}: ${error}`);\n      throw new ImmichStartupError(`Failed to create \"${externalPath} - ${docsMessage}\"`);\n    }\n  }\n","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/immich-app/immich/blob/199723261c6ffa897fec8ccdaea6359e39c37cc3/server/src/services/storage.service.ts#L143-L179","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify the host directory for the failing folder exists and is mounted into the container at the path shown in externalPath.","Ensure the immich server process uid owns or can read the '.immich' file: chown -R <immich-uid>:<immich-gid> <UPLOAD_LOCATION>.","Check the docker-compose volume mapping for the named folder matches StorageCore.getBaseFolder defaults.","If using an external library, confirm the library path is accessible inside the container (docker exec ... ls).","Temporarily remove IMMICH_LOG_LEVEL noise and inspect the preceding log line 'Failed to read (<internalPath>): <error>' for the OS errno."],"exampleFix":"# before: read-only bind\nvolumes:\n  - /mnt/photos:/usr/src/app/upload:ro\n# after: read-write, correct uid\nvolumes:\n  - /mnt/photos:/usr/src/app/upload","handlingStrategy":"validation","validationCode":"import { access, constants } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nasync function canReadImmichMarker(uploadRoot: string, folder: string) {\n  const p = join(uploadRoot, folder, '.immich');\n  try { await access(p, constants.R_OK); return true; }\n  catch { return false; }\n}\n// run for every StorageFolder before starting the server","typeGuard":null,"tryCatchPattern":"try {\n  await storageService.onBootstrap(); // triggers verifyReadAccess\n} catch (e) {\n  if (e instanceof ImmichStartupError && e.message.startsWith('Failed to read')) {\n    // surface a runbook to the operator, do not retry blindly\n  }\n  throw e;\n}","preventionTips":["Run a pre-flight container that execs `ls -la <UPLOAD_LOCATION>/*/.immich` before starting the server.","Pin the immich uid/gid in your compose file and chown host paths to match.","Mount library/upload volumes read-write and verify with `mount` before deploy.","Add a healthcheck that fails on ImmichStartupError so orchestrators do not mark the pod ready."],"tags":["storage","startup","filesystem","permissions","docker"],"backgroundTag":null,"analyzedSha":"199723261c6ffa897fec8ccdaea6359e39c37cc3","analyzedAt":"2026-08-12T04:54:27.085Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}