immich-app/immich · warning

Skipping invalid import path

Error message

Skipping invalid import path: ${importPath}. Reason: ${validation.message}

What it means

When syncing an external library, each configured import path is validated (existence, readability, and that it is an allowed path). If validation fails, the path is skipped and this warning names the path plus the validation reason. Sync continues with the remaining valid paths.

Solutions

  1. Read validation.message in the log for the exact reason and fix that cause
  2. Check the path exists and is readable by the server process user
  3. If on external storage, verify the volume is mounted before sync
  4. Remove or correct the import path in the library settings
  5. Ensure the path does not overlap Immich's internal upload/.immich directories

Example fix

// before
{ this.logger.warn(`Skipping invalid import path: ${importPath}. Reason: ${validation.message}`); }
// after
// fix on deployment side, e.g. ensure mount exists
// mount /mnt/library && chown -R immich:immich /mnt/library
{ this.logger.warn(`Skipping invalid import path: ${importPath}. Reason: ${validation.message}`); }
Defensive patterns

Strategy: validation

Validate before calling

async function importPathUsable(p: string): Promise<boolean> {
  try { const s = await stat(p); return s.isDirectory(); } catch { return false; }
}

Prevention

When it happens

Trigger: An import path no longer exists or is unreadable on disk, points outside the allowed import roots, is a file instead of a directory, or fails validateImportPath for permissions reasons during handleQueueSyncFiles.

Common situations: External storage not mounted at sync time; import path renamed/moved; path added via config pointing at a location the server user cannot read; path blocked because it overlaps internal data directories.

Related errors


AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15). Data as JSON: /api/errors/c5090b151195841e. Report an issue: GitHub.

Appendix: source

Thrown at server/src/services/library.service.ts:630

  @OnJob({ name: JobName.LibrarySyncFilesQueueAll, queue: QueueName.Library })
  async handleQueueSyncFiles(job: JobOf<JobName.LibrarySyncFilesQueueAll>): Promise<JobStatus> {
    const library = await this.libraryRepository.get(job.id);
    if (!library) {
      this.logger.debug(`Library ${job.id} not found, skipping refresh`);
      return JobStatus.Skipped;
    }

    this.logger.debug(`Validating import paths for library ${library.id}...`);

    const validImportPaths: string[] = [];

    for (const importPath of library.importPaths) {
      const validation = await this.validateImportPath(importPath);
      if (validation.isValid) {
        validImportPaths.push(path.normalize(importPath));
      } else {
        this.logger.warn(`Skipping invalid import path: ${importPath}. Reason: ${validation.message}`);
      }
    }

    if (validImportPaths.length === 0) {
      this.logger.warn(`No valid import paths found for library ${library.id}`);

      return JobStatus.Skipped;
    }

    const pathsOnDisk = this.storageRepository.walk({
      pathsToCrawl: validImportPaths,
      includeHidden: false,
      exclusionPatterns: library.exclusionPatterns,
      take: JOBS_LIBRARY_PAGINATION_SIZE,
    });

    let importCount = 0;
    let crawlCount = 0;

View on GitHub (pinned to e55ac299a4)