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

  1. Read path.message in the response - it states the exact reason (missing, no access, etc.).
  2. Ensure the directory exists and is readable by the Immich container user; fix Docker volume mounts so the path is visible inside the container.
  3. Remove or correct the offending import path from the update payload and retry.
  4. 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

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


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