immich-app/immich · error · BadRequestException
Invalid import path: ${path.message}
Error message
Invalid import path: ${path.message} What it means
When updating a library with new importPaths, Immich validates each path (existence, permissions, that it is not inside the library's own exclusion paths, etc.) before persisting. If any path fails validation (path.isValid === false), update aborts with 400 BadRequestException carrying path.message describing why. This prevents recording import paths the worker cannot actually scan.
Source
Thrown at server/src/services/library.service.ts:351
return validation;
}
async validate(id: string, dto: ValidateLibraryDto): Promise<ValidateLibraryResponseDto> {
const importPaths = await Promise.all(
(dto.importPaths || []).map((importPath) => this.validateImportPath(importPath)),
);
return { importPaths };
}
async update(id: string, dto: UpdateLibraryDto): Promise<LibraryResponseDto> {
await this.findOrFail(id);
if (dto.importPaths) {
const validation = await this.validate(id, { importPaths: dto.importPaths });
if (validation.importPaths) {
for (const path of validation.importPaths) {
if (!path.isValid) {
throw new BadRequestException(`Invalid import path: ${path.message}`);
}
}
}
}
const library = await this.libraryRepository.update(id, dto);
return mapLibrary(library);
}
async delete(id: string) {
await this.findOrFail(id);
if (this.watchLibraries) {
await this.unwatch(id);
}
await this.libraryRepository.softDelete(id);
await this.jobRepository.queue({ name: JobName.LibraryDelete, data: { id } });View on GitHub (pinned to 199723261c)
Solutions
- Read path.message in the response - it states the exact reason (missing, no access, etc.).
- Ensure the directory exists and is readable by the Immich container user; fix Docker volume mounts so the path is visible inside the container.
- Remove or correct the offending import path from the update payload and retry.
- On the host: ls -ld <path> and chmod/chown so the immich user can traverse and read it.
Example fix
# before: path not mounted into container
importPaths: ['/data/photos'] # missing in container
# after
docker run -v /host/photos:/data/photos:ro ...
# then PUT /libraries/{id} with importPaths: ['/data/photos'] Defensive patterns
Strategy: validation
Validate before calling
import { promises as fs } from 'fs';
async function assertImportPathsReadable(paths: string[]) {
for (const p of paths) {
const stat = await fs.stat(p).catch(() => null);
if (!stat?.isDirectory()) throw new Error(`Invalid import path: ${p} (missing or not a directory)`);
await fs.access(p, fs.constants.R_OK);
}
} Type guard
const isReadableDir = async (p: string) => {
const s = await fs.stat(p).catch(() => null);
return !!s?.isDirectory();
}; Try / catch
try {
await api.libraryApi.update(id, { importPaths });
} catch (e) {
if (e.status === 400 && /Invalid import path/.test(e.message)) {
// read e.response.message for which path failed and why, fix mounts, retry
} else throw e;
} Prevention
- Inside the container, validate each path exists and is readable before saving.
- Mount host photo directories into the container with correct ownership.
- Surface the per-path message from the API to the operator.
When it happens
Trigger: PUT /libraries/{id} with importPaths containing a path that does not exist, is not readable by the Immich process, is a file rather than a directory, or is otherwise invalid per validate().
Common situations: Mounting host folders incorrectly in Docker so the path is missing inside the container; pointing at a path owned by root with no read permission; typos in the path; passing a file path instead of a directory.
Related errors
- Library ${id} not found
- assetIds, albumId, or userId is required
- Invalid job name
- Notification not found
- User not found
AI-assisted analysis of immich-app/immich@199723261c (2026-08-12).
Data as JSON: /api/errors/6e15f609699a0029.
Report an issue: GitHub.