immich-app/immich · error · BadRequestException
Unable to process profile image
Error message
Unable to process profile image
What it means
A BadRequestException (HTTP 400) thrown by UserService.createProfileImage wrapping the underlying cause when generateProfileImage fails. Before throwing, the service queues deletion of the uploaded temp file, so the uploaded artifact is cleaned up. The original error is attached via { cause } for diagnostics.
Source
Thrown at server/src/services/user.service.ts:118
const user = await this.findOrFail(id, { withDeleted: false });
return mapUser(user);
}
async createProfileImage(auth: AuthDto, file: Express.Multer.File): Promise<CreateProfileImageResponseDto> {
const { profileImagePath: oldPath } = await this.findOrFail(auth.user.id, { withDeleted: false });
let profileImagePath: string;
try {
const config = await this.getConfig({ withCache: true });
profileImagePath = await generateProfileImage(
{ media: this.mediaRepository, crypto: this.cryptoRepository, storageCore: this.storageCore },
config,
auth.user.id,
file.path,
);
} catch (error) {
await this.jobRepository.queue({ name: JobName.FileDelete, data: { files: [file.path] } });
throw new BadRequestException('Unable to process profile image', { cause: error });
}
const user = await this.userRepository.update(auth.user.id, {
profileImagePath,
profileChangedAt: new Date(),
});
const toDelete = [file.path, ...(oldPath ? [oldPath] : [])];
await this.jobRepository.queue({ name: JobName.FileDelete, data: { files: toDelete } });
return {
userId: user.id,
profileImagePath: user.profileImagePath,
profileChangedAt: user.profileChangedAt,
};
}
async deleteProfileImage(auth: AuthDto): Promise<void> {View on GitHub (pinned to 199723261c)
Solutions
- Inspect the cause field of the error response for the underlying sharp/storage error.
- Re-encode the image to JPEG or PNG before uploading and retry.
- Verify the server's sharp installation supports the source format (rebuild sharp or install libvips codecs).
- Check filesystem permissions and free space on the storage volume backing profile images.
Example fix
// before
await api.uploadProfileImage(file); // 400 'Unable to process profile image'
// after
const png = await convertToPng(file);
try {
await api.uploadProfileImage(png);
} catch (e) {
console.error(e.cause); // sharp error detail
} Defensive patterns
Strategy: try-catch
Validate before calling
// Convert/validate the file before upload
const SUPPORTED = ['image/jpeg', 'image/png', 'image/webp'];
if (!SUPPORTED.includes(file.type)) {
return { ok: false, reason: 'Use JPEG, PNG, or WebP' };
}
if (file.size === 0) { return { ok: false, reason: 'File is empty' }; } Type guard
const isProfileImageError = (e: unknown): boolean => typeof e === 'object' && e !== null && (e as any).status === 400 && (e as any).message === 'Unable to process profile image';
Try / catch
try {
return await api.uploadProfileImage(file);
} catch (e) {
if (isProfileImageError(e)) {
notify('Could not process that image. Try a JPEG or PNG.');
console.error('cause:', (e as any).cause);
return null;
}
throw e;
} Prevention
- Pre-validate file type and size client-side before uploading.
- Re-encode unsupported formats to JPEG/PNG before upload.
- Log the cause field to distinguish sharp decode errors from storage errors.
When it happens
Trigger: POST /users/profile-image with a file that sharp cannot decode (corrupt image, unsupported format, zero-byte file, or a non-image mime). Also possible when storage is unavailable or the media/crypto dependencies throw during resize.
Common situations: Uploading a HEIC/AVIF file the sharp build cannot decode; a truncated upload due to network drop; a misconfigured storage folder lacking write permission; sharp native bindings missing in the container.
Related errors
- Unsupported file type ${filename}
- Quota has been exceeded!
- Can't delete a missing profile Image
- Cannot grant permissions you do not have
- API Key not found
AI-assisted analysis of immich-app/immich@199723261c (2026-08-12).
Data as JSON: /api/errors/068f9809783489e0.
Report an issue: GitHub.