fix(runtime,modal): retry a continuing task behind a failed consumer preparation, and do not resume over skipped tasks (#1231) - #1272
Merged
Conversation
…preparation, and do not resume over skipped tasks (#1231) - `resume --retry-failed` now judges whether a consumer ran without a failed continuing producer by the consumer's `prepare:` node, which waits for its producers and admits its optional inputs. A failed or stalled preparation reruns behind the producer's rerun, so the producer is retried with it and no `WORKFLOW_RETRY_SKIPPED` is reported. #1254 counted such a consumer as started and left the producer failed for good. - A consumer whose agent or verifier failed after its preparation finished still counts as started: its rerun starts at once and is admitted without the producer, so rerunning the producer would bring back the false COMPLETE that #1231 fixed. - `modalDurableRunNeedsResume` no longer counts skipped entries as failures a resume could rerun. A retained `stateful-invariant-setup` leaves its later stages skipped, so the Modal worker resumed a run with nothing to reset and waited until its watch timed out. - Amends the #1231 CHANGELOG entry and `docs/reference/cli.md`. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #1254 (issue #1231).
Problem
resume --retry-failedleft a failed continuing producer failed for good when its consumer had failed in preparation. fix(runtime): resume --retry-failed leaves a continuing task its started consumers ran without (#1231) #1254 counted a consumer as started when any of itsprepare:,node:orverify:nodes was in-progress, finished, failed or stalled. A consumer whoseprepare:node failed or stalled has not admitted its optional inputs yet. Its preparation depends on the producers' verifiers, so on retry it reruns behind the producer's rerun and can read it. Example: a failed lens and a failedprepare:catalog. Resume resetprepare:catalogbut not the lens. The catalog then ran without the lens, the lens stayed failed, andWORKFLOW_RETRY_SKIPPEDwrongly said the catalog "already ran without it". Before fix(runtime): resume --retry-failed leaves a continuing task its started consumers ran without (#1231) #1254, both were reset.modalDurableRunNeedsResumecountedskippedcheckpoint entries as failures a resume could rerun, butreadRetainedFailureStateIdsnever retains a skipped entry. On the default topology,dedupe-findingslistsstateful-invariant-setupas an optional input. When the setup fails, it is retained and its later stages in thespecialistsgroup endskipped. The worker then resumed the run,--retry-failedreset nothing, andwaitForTerminalRunwaited untilEVAL_WATCH_TIMEOUT_SECONDSand endedunreachable.Change
failedProducersStartedConsumersOmittedInWorkflow(packages/runtime/src/retry-failed-omissions.ts) now counts a consumer as started only when itsprepare:node isin-progressorfinished.node:Xdepends only onprepare:X, so its rerun starts at once and is admitted before the producer's rerun verifies. Retrying the producer in that case would bring back the false COMPLETE that resume --retry-failed can report COMPLETE after rerunning a continuing node its consumers already ran without #1231 fixed. This is why the PR does not simply skip every failed consumer.readRetainedFailureStateIds) is unchanged. Run state cannot tell a failed preparation from a failed agent, so it still counts a failed consumer as started. That means Modal may name more retained failures than resume does, which can only skip a resume, never start one that resets nothing. A comment now says so.modalDurableRunNeedsResume(packages/modal/src/resume.ts) ignoresskippedentries.--retry-failedreruns a skipped task only by rerunning the failed task it waited on, and that task has its own failed entry. If a run has only skipped entries and no failed ones, it still resumes as before.resume --retry-failedparagraph indocs/reference/cli.md.Not changed:
runSmithersLifecycleCommandstill readsinput.tasks ?? []. The only caller that passesretryFailedalso passestasks.Tests
runtime.test.ts), each with a failed lens and a different catalog state:prepare:catalogfailed or stalled: resume resets bothnode:lensandprepare:catalog, and reports noWORKFLOW_RETRY_SKIPPED. Both cases fail without the fix.node:catalogfailed, orverify:catalogfailed: resume resets the catalog only, leaves the lens failed, and reportsWORKFLOW_RETRY_SKIPPED.resume.test.ts): a failed, retainedstateful-invariant-setupwith skipped later stages does not resume. It still resumes without the retained set, or when another task failed. The test fails without the fix.--retry-failed,readRetainedFailureStateIdsand the optional-prerequisite sync cases: 21 of 21 pass. Full Modal vitest suite: 524 of 524 pass.lint:strict:ci, eslint, prettier,docs:check, and the runtime and modal typechecks are clean.🤖 Generated with Claude Code
The PR appears safe to merge, though two provider-home preflight gaps leave avoidable late workflow failures.
Summary
The PR adjusts failed-task retry decisions and Modal resume handling, and its merge incorporates upstream provider-home preflight, OpenRouter transport settings, and an advisory exception.
HOME, leaving those late failures without its early diagnostic.Reviews (2) · Last reviewed commit: "Merge branch 'unstable' into fix/1231-re..."