{"record":{"id":"19b531517aecd1cf","repo":"immich-app/immich","slug":"unable-to-resolve-realpath","errorCode":null,"errorMessage":"Unable to resolve realpath","messagePattern":"Unable to resolve realpath","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/src/services/download.service.ts","lineNumber":117,"sourceCode":"        continue;\n      }\n\n      const { originalPath, editedPath, originalFileName } = asset;\n\n      let filename = sanitize(originalFileName) || 'unnamed';\n      const count = paths[filename] || 0;\n      paths[filename] = count + 1;\n      if (count !== 0) {\n        const parsedFilename = parse(filename);\n        filename = `${parsedFilename.name}+${count}${parsedFilename.ext}`;\n      }\n\n      let realpath = dto.edited && editedPath ? editedPath : originalPath;\n\n      try {\n        realpath = await this.storageRepository.realpath(realpath);\n      } catch {\n        this.logger.warn('Unable to resolve realpath', { originalPath });\n      }\n\n      zip.addFile(realpath, filename);\n    }\n\n    void zip.finalize();\n\n    return {\n      stream: zip.stream,\n      disposition: dto.archiveName && `attachment; filename*=UTF-8''${encodeURIComponent(dto.archiveName)}.zip`,\n    };\n  }\n}\n","sourceCodeStart":99,"sourceCodeEnd":131,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/services/download.service.ts#L99-L131","documentation":"This warning is logged by the download service when resolving the symbolic/real path of a file to include in a downloadable archive fails. The storage repository's realpath call throws (e.g. the file vanished or the link is broken), and instead of failing the whole archive, the service logs and falls back to the un-resolved path. It is non-fatal by design.","triggerScenarios":"A user downloads an archive while one of the selected files was deleted/moved on disk between selection and zip creation, or the path is a broken symlink that realpath cannot resolve on the storage backend.","commonSituations":"Race between asset selection and download; external storage/volume remounted or offline; broken symlinks in the library; file removed by a concurrent library-deletion job.","solutions":["Verify the file exists at originalPath/editedPath on the storage volume and the symlink target is intact","Check that external library volumes are mounted and reachable by the server","Re-run the download; if persistent, refresh the library so dead entries are purged","If path rewriting matters, fix permissions on parent directories so realpath can traverse them"],"exampleFix":"// before\ntry { realpath = await this.storageRepository.realpath(realpath); } catch { this.logger.warn('Unable to resolve realpath', { originalPath }); }\n// after\ntry { realpath = await this.storageRepository.realpath(realpath); } catch (err) { this.logger.warn('Unable to resolve realpath', { originalPath, error: err }); if (!(await this.storageRepository.exists(realpath))) { continue; } }","handlingStrategy":"try-catch","validationCode":"import { stat, realpath } from 'fs/promises';\nasync function pathResolvable(p: string): Promise<boolean> {\n  try { await realpath(p); return true; } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  realpath = await storageRepository.realpath(realpath);\n} catch {\n  logger.warn('Unable to resolve realpath', { originalPath });\n  // decide: skip the file or proceed with un-resolved path\n}","preventionTips":["Check file/symlink existence before enqueueing downloads","Keep external volumes mounted and monitored","Purge library entries whose files vanished","Log the underlying error, not just the path"],"tags":["filesystem","download","symlink"],"backgroundTag":"file-not-found","analyzedSha":"e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}