From d568c541c5aa75cf501c2e05051c6c65527ad50a Mon Sep 17 00:00:00 2001 From: Peter Wielander Date: Thu, 16 Apr 2026 14:06:39 -0700 Subject: [PATCH] [web] Probe deployment specVersion before replaying run Replay/Re-run now probes the target deployment's specVersion via health check before calling recreateRunFromExisting. Without this, the queue transport is chosen based on the original run's specVersion, which mismatches the deployment when the deployment has been upgraded past the run's specVersion. Falls back to the run's specVersion if the health check fails (e.g. against old deployments without health check support). Co-Authored-By: Claude Opus 4.7 (1M context) Signed-off-by: Peter Wielander --- .changeset/replay-specversion-probe.md | 5 ++++ .../server/workflow-server-actions.server.ts | 24 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 .changeset/replay-specversion-probe.md diff --git a/.changeset/replay-specversion-probe.md b/.changeset/replay-specversion-probe.md new file mode 100644 index 0000000000..e411a8c486 --- /dev/null +++ b/.changeset/replay-specversion-probe.md @@ -0,0 +1,5 @@ +--- +'@workflow/web': patch +--- + +Replay/Re-run probes the target deployment's specVersion via health check before recreating the run, so the correct queue transport (JSON for old deployments, CBOR for new) is used. Falls back to the original run's specVersion if the probe fails. diff --git a/packages/web/app/server/workflow-server-actions.server.ts b/packages/web/app/server/workflow-server-actions.server.ts index ca072d1b77..4d773a04d7 100644 --- a/packages/web/app/server/workflow-server-actions.server.ts +++ b/packages/web/app/server/workflow-server-actions.server.ts @@ -815,11 +815,35 @@ export async function recreateRun( ): Promise> { try { const world = await getWorldFromEnv({ ...worldEnv }); + + // Probe the target deployment's specVersion via health check so we use + // the correct queue transport (JSON for old deployments, CBOR for new). + // Falls back to the run's specVersion inside recreateRunFromExisting + // if the probe fails (e.g. old deployment without health check support). + let specVersion: number | undefined; + try { + let targetDeploymentId = deploymentId; + if (!targetDeploymentId) { + const run = await world.runs.get(runId, { resolveData: 'none' }); + targetDeploymentId = run.deploymentId; + } + const hc = await healthCheck(world, 'workflow', { + deploymentId: targetDeploymentId, + timeout: 10_000, + }); + if (hc.healthy && hc.specVersion != null) { + specVersion = hc.specVersion; + } + } catch { + // Health check failed — fall back to run's specVersion. + } + const newRunId = await workflowRunHelpers.recreateRunFromExisting( world, runId, { deploymentId, + specVersion, } ); return createResponse(newRunId);