Skip to content

fix(media): guard against an upload result without Transloadit results - #2063

Open
giladresisi wants to merge 2 commits into
stagingfrom
fix/uploader-empty-transloadit-result
Open

giladresisi wants to merge 2 commits into
stagingfrom
fix/uploader-empty-transloadit-result

Conversation

@giladresisi

@giladresisi giladresisi commented Sep 10, 2026 •

Copy link
Copy Markdown
Collaborator

What kind of change does this PR introduce?

Bug fix (frontend, media uploader). In the Uppy complete handler in apps/frontend/src/components/media/new.uploader.tsx, the Transloadit branch now reads the assembly results with optional chaining (result.transloadit?.[0]?.results) and, when they are missing or an empty object, unlocks the editor, resets the file-order counter, shows the existing toaster with "Upload failed, please try again" and returns. The success path, the local-storage branch and the save-media calls are unchanged.

Why was this change needed?

Sentry CLOUD-141 (TypeError: Cannot read properties of undefined (reading 'results') and its sibling (reading '0'), same issue) has 50 events from 13 users in the last 7 days on /media and on the Instagram standalone connect page, last seen today.

Root cause, reproduced locally against real Transloadit: the uploader runs with autoProceed, so adding a second file while the first batch is still uploading starts a second batch. @uppy/transloadit keeps a single current assembly and clears it when a batch finishes or errors, so the later batch reaches its post-processing step with no assembly and adds transloadit: [] to the result. The handler then read result.transloadit[0].results and threw. The (reading '0') variant is Uppy emitting complete with a bare { successful, failed, uploadID } result (no transloadit key) when the upload was removed mid-flight. The guard covers both shapes.

Other information:

Two related things deliberately left out:

  • The error handler in the same file calls uppy.clear() during an upload, which Uppy forbids and which is Sentry CLOUD-S1; separate PR.
  • With this guard a fast pair is reported as failed instead of crashing the page, but the files are still not reliably uploaded: depending on timing, the file that started first is sometimes saved and sometimes lost along with the second. Avoiding the race itself (single upload batch, or queueing files added mid-upload) is a behaviour change for a separate decision.

QA

  1. Run with Transloadit configured (TRANSLOADIT_* set, so the Media page uploads through Transloadit rather than local storage)
  2. Open /media, and add two small images one right after the other through the Upload input (fast enough that the second is added while the first is still uploading)
  3. Before this change: the console shows TypeError: Cannot read properties of undefined (reading 'results') from new.uploader.tsx
  4. After this change: no exception; a warning toast "Upload failed, please try again" appears (it auto-hides after a few seconds) and Uppy's status bar reports the failure. Whether the first file is saved depends on timing, so do not treat its absence as a failure of this change
  5. Upload a single image normally and confirm it still saves and appears in the library

Tested locally exactly as above: step 3 reproduced with the guard stashed (exact production message), step 4 verified with the guard in place across several runs (no exception, toast text present in the DOM); in some runs the first file was saved and in others neither file was, which is the race described above. The (reading '0') variant was derived from @uppy/core's #runUpload result fallback and not reproduced.

Checklist:

  • I have read the CONTRIBUTING guide.
  • I have signed the Contributor License Agreement (CLA) (ICLA for individuals, CCLA for entities).
  • I confirm I have not used AI to submit this PR or generate code for it.
  • I checked that there were no similar issues or PRs already open for this.
  • This PR fixes just ONE issue
  • I have filled in the QA section above with real steps to verify this change.

🤖 Generated with Claude Code

https://claude.ai/code/session_017g3KqiuR5TT68XdqpTRbZh

A second upload batch started while the first is in flight ends with no assembly; the complete handler crashed reading results (50 events/7d in prod).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017g3KqiuR5TT68XdqpTRbZh
@postiz-contribution postiz-contribution Bot added the contribution:approved Approved contributor label Sep 10, 2026
@strix-security

strix-security Bot commented Sep 10, 2026 •

Copy link
Copy Markdown

Strix Security Review

No security issues found.

Updated for 7c83f82.


Reviewed by Strix
Re-run review · Configure security review settings

@postiz-agent

postiz-agent Bot commented Sep 10, 2026 •

Copy link
Copy Markdown

✅ Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
✅ Open Source Security 0 0 0 0 0 issues
✅ Licenses 0 0 0 0 0 issues
✅ Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@@ -224,7 +224,13 @@ export function useUppyUploader(props: {

if (transloadit.length > 0) {

This comment was marked as outdated.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid point, thanks. An empty results object was not one of the shapes behind the Sentry issue (those were a missing or empty transloadit array), but it would have fallen through to onUploadSuccess with an empty list and unlocked the editor silently. Extended the guard in 7c83f82 to treat an empty results object the same way: reset, warning toast, return. Retested the two batch race locally: no exception, toast shown.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contribution:approved Approved contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant