immich-app/immich · error · Error

errors.unable_to_upload_file

Error message

errors.unable_to_upload_file

What it means

Thrown by the web upload pipeline (file-uploader.ts) when the HTTP response from POST /assets has a status code outside [200,201]. The message is the i18n key 'errors.unable_to_upload_file'. The actual server-side reason is in the response body but is not surfaced in this generic client error.

Source

Thrown at web/src/lib/utils/file-uploader.ts:231

          };
        }
      } catch (error) {
        console.error(`Error calculating sha1 file=${assetFile.name})`, error);
      }
    }

    if (!responseData) {
      const queryParams = asQueryString(authManager.params);

      uploadAssetsStore.updateItem(deviceAssetId, { message: $t('asset_uploading') });
      const response = await uploadRequest<AssetMediaResponseDto>({
        url: getBaseUrl() + '/assets' + (queryParams ? `?${queryParams}` : ''),
        data: formData,
        onUploadProgress: (event) => uploadAssetsStore.updateProgress(deviceAssetId, event.loaded, event.total),
      });

      if (![200, 201].includes(response.status)) {
        throw new Error($t('errors.unable_to_upload_file'));
      }

      responseData = response.data;
    }

    if (responseData.status === AssetMediaStatus.Duplicate) {
      uploadAssetsStore.track('duplicate');
    } else {
      uploadAssetsStore.track('success');
    }

    if (albumId && !authManager.isSharedLink) {
      uploadAssetsStore.updateItem(deviceAssetId, { message: $t('asset_adding_to_album') });
      await addAssetsToAlbums([albumId], [responseData.id], { notify: false });
      uploadAssetsStore.updateItem(deviceAssetId, { message: $t('asset_added_to_album') });
    }

    uploadAssetsStore.updateItem(deviceAssetId, {

View on GitHub (pinned to 199723261c)

Solutions

  1. Open the browser DevTools Network tab and inspect the /assets response status and body for the real server error.
  2. Raise the reverse-proxy client_max_body_size / proxy body limit to exceed the largest uploaded file (e.g. 1G+).
  3. Re-authenticate if the session expired; check server logs for the matching request.
  4. Verify server disk space and upload directory permissions.

Example fix

// before — nginx
client_max_body_size 100m;

# after
client_max_body_size 0;   # or a large value > max upload
proxy_request_buffering off;
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: ensure file is readable and within allowed size
if (file.size > MAX_BYTES) { notify('File too large'); return; }

Type guard

const isUploadable = (f: File) => f.size > 0 && f.size <= MAX_BYTES && f.type.startsWith('image/');

Try / catch

try { await uploadFile(file); }
catch (e) { if (e.message === $t('errors.unable_to_upload_file')) { /* inspect last response, retry once */ } else throw e; }

Prevention

When it happens

Trigger: Browser upload where the server returns 4xx/5xx (e.g. 400 bad request, 413 payload too large, 401 unauthorized, 500 server error) for one of the queued asset files.

Common situations: Reverse proxy (nginx/Cloudflare) body-size limit smaller than the uploaded file; expired session/cookie; server disk full or upload folder not writable; network interruption returning a proxy error page; rate limiting.

Related errors


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