From 6e6b85098e37208c4fa208aac4f2d2a1ba12cd0d Mon Sep 17 00:00:00 2001 From: Daniel Dybing Date: Sun, 7 Dec 2025 14:59:07 +0100 Subject: [PATCH] fix(core): handle image-blob reduce errors more gracefully (#14056) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR is related to issue https://github.com/toeverything/AFFiNE/issues/14018 When uploading a new profile photo avatar the Pica function, which is responsible for reducing and resizing the profile photo, may crash if the browser's Fingerprint Protection is enabled. This is because Fingerprint Protection prevents Pica from modifying the canvas. This fix introduces a try-catch inside the function that calls the reduction and resizing of the photo. Also, the Error object is no longer passed directly to the notification service, which also caused issues previously. Now a message will appear that tells the user that the upload failed and to check the browser's fingerprint protection (check photo below). Affected files: packages/frontend/core/src/utils/reduce-image.ts new_error I'm open to any suggestions in terms of wording of the error messages. ## Summary by CodeRabbit * **Bug Fixes** * Improved error handling for image compression with clearer, user-facing messages when compression is blocked or fails. * Ensures the original or reduced image is reliably returned as a fallback if compression is not performed. * Preserves file metadata (original lastModified, name, type) when returning processed files. ✏️ Tip: You can customize this high-level summary in your review settings. --------- Co-authored-by: DarkSky Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com> --- .../frontend/core/src/utils/reduce-image.ts | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/packages/frontend/core/src/utils/reduce-image.ts b/packages/frontend/core/src/utils/reduce-image.ts index c255131355..5178f36c2d 100644 --- a/packages/frontend/core/src/utils/reduce-image.ts +++ b/packages/frontend/core/src/utils/reduce-image.ts @@ -20,23 +20,33 @@ export const validateAndReduceImage = async (file: File): Promise => { const sizeInMB = file.size / (1024 * 1024); if (sizeInMB > 10 || img.width > 4000 || img.height > 4000) { // Compress the file to less than 10MB - const compressedImg = await reduce().toBlob(file, { - max: 4000, - unsharpAmount: 80, - unsharpRadius: 0.6, - unsharpThreshold: 2, - }); - return compressedImg; + + try { + const compressedImg = await reduce().toBlob(file, { + max: 4000, + unsharpAmount: 80, + unsharpRadius: 0.6, + unsharpThreshold: 2, + }); + return compressedImg; + } catch (error) { + if (error instanceof Error) { + throw new Error( + 'Image processing failed. This can happen if fingerprint protection is enabled in your browser. Please check your browser settings and try again.' + ); + } else { + throw new Error('Unknown error occurred'); + } + } } return file; }; - try { - const reducedBlob = await decodeAndReduceImage(); + const reducedBlob = await decodeAndReduceImage(); - return new File([reducedBlob], file.name, { type: file.type }); - } catch (error) { - throw new Error('Image could not be reduce :' + error); - } + return new File([reducedBlob], file.name, { + type: file.type, + lastModified: file.lastModified, + }); };