OUT-4154: guard image insert against destroyed editor - #237
Merged
Conversation
The async image upload in useFileHandlers could resume after the TipTap editor was torn down (unmount / re-init), calling chain() on an editor whose commandManager is null and throwing an unhandled rejection (Sentry CLIENT-HOME-V3-1W). - Bail on currentEditor.isDestroyed at the top of onload and after the Supabase upload await - Wrap the upload + src swap in try/catch so a failed upload no longer surfaces as an unhandled rejection Fixes CLIENT-HOME-V3-1W Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR hardens asynchronous editor image insertion against editor teardown and rejected uploads.
Confidence Score: 5/5The PR appears safe to merge, with the asynchronous teardown and upload-failure paths handled without changing successful image insertion. The changed callback checks editor viability before each lifecycle-sensitive phase and catches upload failures, while the normal path still uploads the file, replaces the temporary source, and synchronizes the resulting HTML. Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant Reader as FileReader
participant Editor
participant Storage
User->>Reader: Select or paste image
Reader-->>Editor: onload(data URL)
alt Editor already destroyed
Editor-->>User: Stop without insertion
else Editor active
Editor->>Editor: Insert temporary image
Editor->>Storage: Upload file
alt Upload fails
Storage-->>Editor: Reject
Editor->>Editor: Log error and retain placeholder
else Upload succeeds
Storage-->>Editor: Return file path
alt Editor destroyed during upload
Editor->>Editor: Log warning and retain placeholder
else Editor active
Editor->>Editor: Replace src with proxy URL
Editor->>Editor: Synchronize serialized HTML
end
end
end
Reviews (1): Last reviewed commit: "fix(OUT-4154): guard image insert agains..." | Re-trigger Greptile |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes
TypeError: Cannot read properties of null (reading 'chain')(SentryCLIENT-HOME-V3-1W/ OUT-4154) in the editor's file-insertion flow.Root cause:
fileReader.onloadinuseFileHandlers.tsxis async. It inserts a placeholder image,awaitsuploadFileToSupabase(file)(a network round-trip), then callscurrentEditor.chain()...to swap the blob for the proxy URL. If the TipTap editor is destroyed during that window (component unmount, navigation, oruseEditorre-init when thecontentprop changes), the resumed continuation calls.chain()on a torn-down editor whose internalcommandManageris null → the crash. Becauseonloadisasyncwith notry/catch, it surfaced as an unhandled promise rejection.Fix:
currentEditor.isDestroyedat the top ofonload(guards the synchronouschain()—onloadfires on a later tick, so the editor may already be gone) and again after the uploadawait.try/catchso a failed/aborted upload keeps the blob placeholder instead of throwing an unhandled rejection.console.warnbreadcrumb when the destroyed-editor guard trips, to retain visibility (the base64 placeholder stays in content, same state as before the crash — just no longer fatal).Testing Criteria
srcswaps from the base64 blob to the/api/media/imageproxy URL (happy path unchanged). (Loom to be added)Notes
Editor.isDestroyedis the canonical "editor still usable" check.Impact & Surface Area of Change
src/features/editor/hooks/useFileHandlers.tsx(image/file insertion). Happy path is unchanged; the new guards only short-circuit when the editor is already destroyed or the upload rejects. Watch the editor image-insert flow for regressions.🤖 Generated with Claude Code