fix(core): fallback to safe string payload in stringifyIO when superjson fails - #4931
fix(core): fallback to safe string payload in stringifyIO when superjson fails#4931Tyagiquamar wants to merge 3 commits into
Conversation
🦋 Changeset detectedLatest commit: 74db548 The changes in this PR will be included in the next version bump. This PR includes changesets to release 27 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Hi @Tyagiquamar, thanks for your interest in contributing! This project requires that pull request authors are vouched, and you are not in the list of vouched users. This PR will be closed automatically. See https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md for more details. |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (5)
WalkthroughThe changes fix Severity of issue fixed: Medium ✨ Finishing Touches🧪 Generate unit tests (beta)
Warning Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
| const data = JSON.stringify(value, makeSafeReplacer()); | ||
|
|
||
| return { data, dataType: "application/json" }; |
There was a problem hiding this comment.
🟡 Undefined fallback drops payloads
When fallback serialization returns undefined, stringifyIO emits an empty JSON packet. Parsing replaces the original value with undefined.
Learn more
JSON.stringify returns undefined rather than throwing for some top-level values. The returned IOPacket therefore has no data, and parsePacket treats it as an absent value. The outer fallback never runs because no exception occurred.
Example: A custom class instance rejected by SuperJSON can define toJSON() to return undefined. The JSON fallback then produces no data, and the receiver gets undefined instead of a textual representation.
Recommended fix: Treat an undefined result as a failed JSON serialization and return the existing text/plain representation.
| const data = JSON.stringify(value, makeSafeReplacer()); | |
| return { data, dataType: "application/json" }; | |
| const data = JSON.stringify(value, makeSafeReplacer()); | |
| return data === undefined | |
| ? { data: String(value), dataType: "text/plain" } | |
| : { data, dataType: "application/json" }; |
Was this helpful? React with 👍 or 👎 to provide feedback.
| --- | ||
| "@trigger.dev/sdk": patch | ||
| --- | ||
|
|
||
| `envvars.update()`: calling it outside a task run no longer throws `ReferenceError: name is not defined`. The variable name is now resolved from the positional arguments, matching the other env var methods, and a missing name raises a descriptive `name is required` error instead. |
| it("fallback returns string data when superjson fails", async () => { | ||
| // Create an object where superjson.stringify throws or handles non-standard values | ||
| const cyclic: any = { name: "test" }; | ||
| cyclic.self = cyclic; | ||
|
|
||
| const result = await stringifyIO(cyclic); | ||
| expect(typeof result.data).toBe("string"); | ||
| }); |
IOPacket defines data?: string | undefined. When superjson.stringify(value) failed in stringifyIO(), the catch block previously returned { data: value, dataType: 'application/json' }. If value was an object, BigInt, or un-superjson-able data structure, packet.data received a raw object instead of a string, causing downstream Buffer.byteLength and offloading calculations to fail.
This fix updates the catch block of stringifyIO() to safely format value using JSON.stringify(value, makeSafeReplacer()) (falling back to String(value)), preserving the string type contract of IOPacket.data.