immich-app/immich · critical · ImmichStartupError

Failed to write "${externalPath} - ${docsMessage}"

Error message

Failed to write "${externalPath} - ${docsMessage}"

What it means

Thrown by StorageService.verifyWriteAccess at startup when overwriteFile of the '.immich' marker file fails. This proves the volume is writable, not just creatable; failure aborts startup (ImmichStartupError) with the external path and folder-checks doc link.

Source

Thrown at server/src/services/storage.service.ts:186

      this.storageRepository.mkdirSync(folderPath);
      await this.storageRepository.createFile(internalPath, Buffer.from(Date.now().toString()));
    } catch (error) {
      if ((error as NodeJS.ErrnoException).code === 'EEXIST') {
        this.logger.warn('Found existing mount file, skipping creation');
        return;
      }
      this.logger.error(`Failed to create ${internalPath}: ${error}`);
      throw new ImmichStartupError(`Failed to create "${externalPath} - ${docsMessage}"`);
    }
  }

  private async verifyWriteAccess(folder: StorageFolder) {
    const { internalPath, externalPath } = this.getMountFilePaths(folder);
    try {
      await this.storageRepository.overwriteFile(internalPath, Buffer.from(Date.now().toString()));
    } catch (error) {
      this.logger.error(`Failed to write ${internalPath}: ${error}`);
      throw new ImmichStartupError(`Failed to write "${externalPath} - ${docsMessage}"`);
    }
  }

  private getMountFilePaths(folder: StorageFolder) {
    const folderPath = StorageCore.getBaseFolder(folder);
    const internalPath = join(folderPath, '.immich');
    const externalPath = `<UPLOAD_LOCATION>/${folder}/.immich`;

    return { folderPath, internalPath, externalPath };
  }
}

View on GitHub (pinned to 199723261c)

Solutions

  1. Confirm the volume is mounted read-write: mount | grep <path>.
  2. Remove any immutable attribute: chattr -i <UPLOAD_LOCATION>/<folder>/.immich.
  3. Raise the user's disk quota or move to a volume with space.
  4. Verify ACLs allow the immich uid to overwrite existing files: getfacl <folder>.
  5. Re-mount the share writable (CIFS: remove 'ro', NFS: verify exports allow rw).

Example fix

# read-only NFS export
mount -o remount,rw /mnt/library
Defensive patterns

Strategy: validation

Validate before calling

import { open, writeFile } from 'node:fs/promises';
async function canOverwrite(p: string) {
  try { await writeFile(p, Buffer.from('probe'), { flag: 'r+' }); return true; }
  catch { try { await writeFile(p, Buffer.from('probe')); return true; } catch { return false; } }
}

Try / catch

try { await storageService.onBootstrap(); }
catch (e) {
  if (e instanceof ImmichStartupError && /Failed to write/.test(e.message)) {
    // remount share read-write or fix ACLs, then restart
  }
}

Prevention

When it happens

Trigger: Server boot, folder-integrity phase: storageRepository.overwriteFile(internalPath, Buffer) rejects after createMountFile succeeded, e.g. file became read-only between checks or the FS rejects truncation.

Common situations: NFS/CIFS mount mounted read-only after creation; immutable/chattr +i set on '.immich'; quota exhausted between create and overwrite; container running as a uid that can create but not overwrite due to ACLs.

Related errors


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