Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/snapshot-route-zod-v4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@trigger.dev/core": patch
---

Fixes warm starts silently failing for deployments built with 4.6.0 to 4.6.3 in projects that resolve `zod` to a 3.x release. The runner could not parse the run handed to it by the warm-start service and exited, leaving the run waiting until the platform redrove it a few minutes later and started it cold. Redeploy to pick up the fix.
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,83 @@ describe("schema composition compatibility", () => {
resource: { id: "my-webhook" },
});
});

it.each([
{ name: "zod", v3: require.resolve("zod/v3"), v4: require.resolve("zod/v4") },
{
name: "zod-v3-floor",
v3: require.resolve("zod-v3-floor/v3"),
v4: require.resolve("zod-v3-floor/v4"),
},
])("parses run engine worker schemas with $name and a Zod 3 root", async ({ v3, v4 }) => {
// The warm-start client parses DequeuedMessage inside the deployed runner, where the root
// "zod" import resolves to whatever the user's project installed. A leaf schema built on the
// Zod 3 API and composed into a Zod 4 object throws on every parse, not just on bad input.
const result = await build({
stdin: {
contents: `
import { DequeuedMessage } from "./src/v3/schemas/runEngine.ts";
import { WorkerApiRunAttemptStartRequestBody } from "./src/v3/runEngineWorker/supervisor/schemas.ts";

const snapshotRoute = { version: 1, residency: "postgres", organizationId: "org_1" };

export const parsed = {
dequeued: DequeuedMessage.parse({
version: "1",
snapshotRoute,
dequeuedAt: "2026-01-01T00:00:00.000Z",
snapshot: {
id: "snapshot_1",
friendlyId: "snapshot_1",
executionStatus: "PENDING_EXECUTING",
description: "Run was dequeued for execution",
createdAt: "2026-01-01T00:00:00.000Z",
},
completedWaitpoints: [],
backgroundWorker: { id: "worker_1", friendlyId: "worker_1", version: "20260101.1" },
deployment: { id: "deployment_1", friendlyId: "deployment_1" },
run: {
id: "run_1",
friendlyId: "run_1",
isTest: false,
machine: { name: "small-1x", cpu: 0.5, memory: 0.5, centsPerMs: 0 },
attemptNumber: 1,
masterQueue: "main",
traceContext: {},
},
environment: { id: "env_1", type: "PRODUCTION" },
organization: { id: "org_1" },
project: { id: "proj_1" },
}),
attemptStart: WorkerApiRunAttemptStartRequestBody.parse({ isWarmStart: true, snapshotRoute }),
};
`,
loader: "ts",
resolveDir: packageRoot,
},
bundle: true,
format: "esm",
platform: "node",
target: "node20",
write: false,
plugins: [
{
name: "resolve-root-zod-to-v3",
setup(build) {
build.onResolve({ filter: /^zod$/ }, () => ({ path: v3 }));
build.onResolve({ filter: /^zod\/v4$/ }, () => ({ path: v4 }));
},
},
],
});

const bundledModule = await import(
`data:text/javascript;base64,${Buffer.from(result.outputFiles[0]!.text).toString("base64")}`
);

expect(bundledModule.parsed).toMatchObject({
dequeued: { run: { id: "run_1" }, snapshotRoute: { residency: "postgres" } },
attemptStart: { isWarmStart: true, snapshotRoute: { residency: "postgres" } },
});
});
});
2 changes: 1 addition & 1 deletion packages/core/src/v3/schemas/snapshotRoute.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from "zod/v4";

/**
* A run's versioned storage route (control metadata, never a TRES column), stamped on the queue message
Expand Down
Loading