-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Provide environment information
v4.4.3
Describe the bug
When a task returns an object that includes undefined for optional fields, runs.retrieve() can return those fields as null if the output is small enough to be returned inline from the API.
Expected: values round-trip like a full superjson deserialize (typically undefined for optional fields), so z.number().optional) still works.
Actual: inline responses can return superjson’s JSON “shape” where undefined becomes null.
Large/offloaded outputs (presigned blob path) deserialize correctly and return undefined.
It's most easily with undefined coming back as null, but anything superjson normally preserves (Date, Map, Set, BigInt, RegExp, etc.) is also wrong on small inline outputs, big outputs fetched via presign still look fine.
Reproduction repo
n/a
To reproduce
- Add tasks:
import { schemaTask } from "@trigger.dev/sdk";
import { z } from "zod";
export const smallOptionalUndefined = schemaTask({
id: "small-optional-undefined",
schema: z.object({}),
run: async () => ({ value: 1, optional: undefined as undefined | number }),
});
export const bigOptionalUndefined = schemaTask({
id: "big-optional-undefined",
schema: z.object({}),
run: async () => ({
value: 1,
optional: undefined as undefined | number,
filler: "x".repeat(200 * 1024),
}),
});
2 . Start the dev server:
npx trigger.dev dev
3. Trigger and retrieve:
import { runs, tasks } from "@trigger.dev/sdk";
async function waitForRun(id: string) {
while (true) {
const run = await runs.retrieve(id);
if (run.status === "COMPLETED") return run;
if (run.status === "FAILED" || run.status === "CANCELED") {
throw new Error(`Run ${id} ended with status ${run.status}`);
}
await new Promise((r) => setTimeout(r, 1000));
}
}
const small = await waitForRun((await tasks.trigger("small-optional-undefined", {})).id);
const big = await waitForRun((await tasks.trigger("big-optional-undefined", {})).id);
console.log("small.optional =", (small.output as any)?.optional); // observed: null
console.log("big.optional =", (big.output as any)?.optional); // observed: undefined
Expected:
small.optional = undefined
big.optional = undefined
Observed:
small.optional = null
big.optional = undefined
Additional information
No response