Hacktoberfest 2026: die Issues, die Maintainer für den Oktober markiert haben – offen und einsteigerfreundlich. Hacktoberfest-Issues durchsuchen

Signal delivered after a run's version is unregistered is consumed, leaving the run stranded in "running" (half-transition)

Offen
#24 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
4/5
Geschätzter Aufwand
1-2 Tage
Anfängerfreundlichkeit
52/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Aktiv
Tech-Stack
postgresql, typescript

Rechercherichtung

Start with the signal delivery path in packages/workflow-runtime/src/in-memory-store.ts and the version mismatch handling in packages/workflow-core/src/engine/run-workflow.ts; then read packages/workflow-runtime/src/runtime-driver.ts. Trace how delivery, mismatch handling, and lease release affect the stored run, using the described reproduction as a guide. Done means a mismatched version cannot leave the run running with no lease and no pending wait; confirm the selected outcome in the tests.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

Versions

@tanstack/workflow-core 0.0.4, @tanstack/workflow-runtime 0.0.3. I see the same result on main at b928717, from a Postgres-store test suite rather than this exact snippet.

Describe the bug and the steps to reproduce it

The docs say to keep old versions in previousVersions until their runs terminate, so deploying v2 without v1 while a v1 run is paused is a deployment mistake. The bug is what that mistake does to the run: delivering a signal leaves it half-transitioned, and the public runtime API has no way to get it back.

Steps: pause a run on v1, deploy v2 without previousVersions: { v1 }, then deliver the signal through runtime.deliverSignal.

  1. The store accepts the delivery and clears the waiting state (in-memory-store.ts). The signal is consumed and the run moves from paused to running.
  2. The core then finds no matching version, emits RUN_ERRORED { code: 'workflow_version_mismatch' } and returns without saving anything (run-workflow.ts).
  3. The runtime releases the lease (runtime-driver.ts).

The run ends up running, with no lease, no error and nothing awaited. Correcting the deploy doesn't help:

  • Rolling back to a runtime that registers v1 and re-delivering returns not-waiting.
  • Stale-run recovery (#15) only claims runs whose lease has expired, so it never selects a run whose lease was released.

The docs promise a RUN_ERRORED event; they don't clearly say the run should be persisted as errored, so I'm not assuming that's the intended fix. Either outcome would be fine, as long as the run doesn't end up in this in-between state:

  • (a) reject the delivery before it is consumed, leaving the run paused, so fixing the deploy lets it resume. This seems safer for rolling deploys.
  • (b) persist a terminal errored status with the mismatch code, so the failure is visible and the run is no longer running.
Your Minimal, Reproducible Example
import { createWorkflow } from '@tanstack/workflow-core'
import { defineWorkflowRuntime, inMemoryWorkflowExecutionStore } from '@tanstack/workflow-runtime'

const def = (v: string) =>
  createWorkflow({ id: 'wf', version: v }).handler(async (ctx) => {
    const x = await ctx.waitForEvent<{ ok: boolean }>('go', { id: 'go' })
    return x.ok
  })
const store = inMemoryWorkflowExecutionStore()
const v1 = defineWorkflowRuntime({ store, workflows: { wf: { load: async () => def('v1'), version: 'v1' } } })
const v2 = defineWorkflowRuntime({ store, workflows: { wf: { load: async () => def('v2'), version: 'v2' } } })

await v1.startRun({ workflowId: 'wf', runId: 'r2', input: {} })
const res = await v2.deliverSignal({ runId: 'r2', stepId: 'go', name: 'go', signalId: 's1', payload: { ok: true } })
const run = await store.loadRun('r2')
console.log(res.kind, run?.status, run?.error, run?.lease) // 'running' 'running' undefined undefined

const retry = await v1.deliverSignal({ runId: 'r2', stepId: 'go', name: 'go', signalId: 's2', payload: { ok: true } })
console.log(retry.kind) // 'not-waiting': even after the deploy is fixed, the run can't continue
Do you intend to try to help solve this bug with your own PR?

Yes — happy to put up a PR once there's agreement on (a) vs (b).

Terms & Code of Conduct
  • I agree to follow this project's Code of Conduct
  • I understand that if my bug cannot be reliably reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.
Vorherrschende Sprache
TypeScript
Sterne
221
Forks
10
PR-Merge-Kennzahlen
Keine gemergten PRs in 30 T.

Entwicklungsumgebung

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus TanStack/workflow

Alle Issues in TanStack/workflow

Ähnliche Issues

Weitere Issues zu TypeScript

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.