Immich Upload Fails: Fix Storage Paths, Permissions, and Disk Space

Same Ubuntu 24.04 trial host as the minimal install post · Immich v3 · UPLOAD_LOCATION=./library

When Immich rejects uploads or the server never becomes healthy after a path change, the cause is usually free space, a bad UPLOAD_LOCATION, or host permissions — not the web UI itself.

Symptom matrix

What you seeCheck first
Spinner forever / empty libraryDisk space + UPLOAD_LOCATION bind mount
Insufficient storagedf -h on the host path behind the volume
HTTP 413 / proxy errorsReverse-proxy body size (HTTPS post)
Server restarts / never healthyFolder integrity checks under UPLOAD_LOCATION
Mobile upload fails, web worksClient network / HTTPS URL settings

Official reference: System integrity — folder checks.

1. Free space

df -h /home/ubuntu/immich-app
du -sh ./library ./postgres 2>/dev/null

Thumbnails and encoded video need headroom beyond the originals. If the filesystem is near full, free space or move the library (external storage).

df showing free space on the root filesystem, and a library listing with upload, thumbs, and encoded-video directories.
df and library listing on a healthy host.

2. Confirm UPLOAD_LOCATION matches the bind mount

In .env:

grep UPLOAD_LOCATION .env
grep of the host env file showing UPLOAD_LOCATION set to ./library.
UPLOAD_LOCATION in .env. The database password in this shot is a disposable demo value. Do not reuse it, and do not treat it as an admin password.

That path must exist on the host and must be the same directory mounted into the server container. If you regenerate env files from the compose generator, merge carefully — do not overwrite a customized path by accident.

3. Broken path: what Immich logs look like

On the trial host we pointed UPLOAD_LOCATION at an empty, unusable directory. The microservices worker failed the folder check and exited:

Failed to read: "<UPLOAD_LOCATION>/encoded-video/.immich (...)"
Please see https://docs.immich.app/administration/system-integrity#folder-checks
Server logs where the microservices worker failed to read the encoded-video marker file and exited.
Server logs after a bad UPLOAD_LOCATION.

Fix:

  1. Restore a valid UPLOAD_LOCATION (existing library tree with the expected subfolders).
  2. docker compose up -d
  3. Confirm docker compose ps shows a healthy immich_server.

4. Permissions

Containers often write as root; host directories may be owned by your SSH user. Patterns that work on Ubuntu with the official Compose file:

  • Ensure the upload directory tree exists before up -d.
  • If Immich cannot create .immich marker files, fix ownership on the host path (for example sudo chown -R 1000:1000 ./library when the container runs as UID 1000 — match whatever docker compose exec immich-server id reports on your box).
  • Avoid mounting the library read-only.

5. Read logs during a failed upload

docker logs immich_server --tail 100

Map lines to a missing path, permission denied, a full disk, or proxy and client size limits. If HTTPS is already in front, raise client_max_body_size (Nginx) or the Caddy body limit — covered in Immich Behind HTTPS: Nginx or Caddy Reverse Proxy Basics.

6. Verify the fix

Re-upload the same file. Confirm:

  • The timeline shows the asset
  • A new object appears under UPLOAD_LOCATION on disk
Immich timeline with gray.jpg after a successful upload. The thumbnail is a flat gray square.
Successful upload in the Immich UI. The asset is a flat gray test JPEG, so the tile has no scene in it.