{"record":{"id":"6e15f609699a0029","repo":"immich-app/immich","slug":"invalid-import-path-path-message","errorCode":null,"errorMessage":"Invalid import path: ${path.message}","messagePattern":"Invalid import path: (.+?)","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server/src/services/library.service.ts","lineNumber":351,"sourceCode":"    return validation;\n  }\n\n  async validate(id: string, dto: ValidateLibraryDto): Promise<ValidateLibraryResponseDto> {\n    const importPaths = await Promise.all(\n      (dto.importPaths || []).map((importPath) => this.validateImportPath(importPath)),\n    );\n    return { importPaths };\n  }\n\n  async update(id: string, dto: UpdateLibraryDto): Promise<LibraryResponseDto> {\n    await this.findOrFail(id);\n\n    if (dto.importPaths) {\n      const validation = await this.validate(id, { importPaths: dto.importPaths });\n      if (validation.importPaths) {\n        for (const path of validation.importPaths) {\n          if (!path.isValid) {\n            throw new BadRequestException(`Invalid import path: ${path.message}`);\n          }\n        }\n      }\n    }\n\n    const library = await this.libraryRepository.update(id, dto);\n    return mapLibrary(library);\n  }\n\n  async delete(id: string) {\n    await this.findOrFail(id);\n\n    if (this.watchLibraries) {\n      await this.unwatch(id);\n    }\n\n    await this.libraryRepository.softDelete(id);\n    await this.jobRepository.queue({ name: JobName.LibraryDelete, data: { id } });","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/services/library.service.ts#L333-L369","documentation":"This error is thrown by Immich's LibraryService.update when a library update request includes importPaths entries that fail validation. Before persisting the update, the service calls validate() and if any validated path has isValid=false, it aborts with a BadRequestException carrying the validator's per-path message. It protects the library from being saved with unreadable or disallowed import directories.","triggerScenarios":"Calling the library update API (PATCH/PUT update) with dto.importPaths containing a path that the validator rejects (e.g. directory does not exist, is not readable, is a file rather than a directory, is a symlink, or points outside allowed boundaries such as an excluded/mount-invalid path).","commonSituations":"Admin adds an import folder via the UI/API after the folder was deleted or renamed on disk; Docker volume mounts changed so the container no longer sees the path; Windows vs Linux path separators or trailing-slash typos; path points to the upload/encoded-video/backup internal locations which are not allowed as import paths.","solutions":["Check the per-path message in the error (it names the failing reason) and fix the path on disk so it exists, is a directory, and is readable by the server process","Verify Docker volume mounts so the path is visible inside the server container","Remove or correct the invalid entry in the update request's importPaths and resubmit","Use a path that is not one of Immich's reserved internal directories (upload/, library/, encoded-video/, etc.)"],"exampleFix":"// before\nawait api.libraryApi.updateLibrary(id, { importPaths: ['/photos/old-folder'] }); // folder no longer exists\n// after\nawait fs.mkdir('/photos/old-folder', { recursive: true }); // or point to an existing, mounted, allowed directory\nawait api.libraryApi.updateLibrary(id, { importPaths: ['/photos/old-folder'] });","handlingStrategy":"validation","validationCode":"for (const p of importPaths) {\n  const stat = await fs.promises.stat(p).catch(() => null);\n  if (!stat || !stat.isDirectory()) throw new Error(`Import path is not a directory: ${p}`);\n  await fs.promises.access(p, fs.constants.R_OK); // readable\n}","typeGuard":"function isValidImportPath(p) {\n  return typeof p === 'string' && p.trim().length > 0 && require('path').isAbsolute(p);\n}","tryCatchPattern":"try {\n  await api.libraryApi.updateLibrary(id, { importPaths });\n} catch (e) {\n  if (e?.response?.status === 400 && String(e.message).includes('Invalid import path')) {\n    console.warn('Rejected paths:', e.response.data?.message); // fix or drop offending paths and retry\n  } else throw e;\n}","preventionTips":["Stat each path for existence and directory-ness before sending an update","Ensure Docker volume mounts make the path visible inside the server container","Avoid Immich-reserved internal directories as import paths","Normalize path separators and avoid trailing slashes/relative paths"],"tags":["validation","filesystem","bad-request","library"],"backgroundTag":"invalid-argument-value","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"}