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
- Open the browser DevTools Network tab and inspect the /assets response status and body for the real server error.
- Raise the reverse-proxy client_max_body_size / proxy body limit to exceed the largest uploaded file (e.g. 1G+).
- Re-authenticate if the session expired; check server logs for the matching request.
- 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
- Raise reverse-proxy client_max_body_size above the largest upload.
- Show the server response body to the user for actionable diagnosis.
- Retry failed uploads with exponential backoff.
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
- Failed to fetch activation key
- Machine learning request '${JSON.stringify(config)}' failed
- Unsupported file type ${filename}
- Quota has been exceeded!
- Invalid backup name!
AI-assisted analysis of immich-app/immich@199723261c (2026-08-12).
Data as JSON: /api/errors/50b994ac3ad84c35.
Report an issue: GitHub.