Repository navigation
Description
vp run kills in-flight sibling tasks when one dependsOn task fails. There is no documented flag or task option to run every sibling to completion.
Version
vp v1.4.0 (local vite-plus@1.4.0): vite v8.3.5, rolldown v1.2.15, vitest v5.0.5, oxfmt v0.74.0, oxlint v1.89.0.
vp run --help on this build lists --ignore-depends-on, --parallel, --no-cache, and --concurrency-limit. It does not list --no-bail, --continue, or any other "run the rest" switch. docs/config/run.md documents command, dependsOn, and cache. dependsOn is described as tasks that must complete successfully before the parent starts. Nothing there says an in-flight sibling is allowed to finish after a peer fails.
Fixture
vite.config.ts:
import { defineConfig } from "vite-plus";
export default defineConfig({
run: {
enablePrePostScripts: false,
cache: { scripts: false, tasks: false },
tasks: {
"child:fail": {
command: "sh -c 'echo FAIL_START; exit 1'",
cache: false,
},
"child:sentinel": {
command: "sh -c 'echo SENTINEL_START; echo start > sentinel-start.txt; sleep 3; echo SENTINEL_DONE; echo done > sentinel-done.txt'",
cache: false,
},
"gate:probe": {
command: "echo parent-ran",
dependsOn: ["child:fail", "child:sentinel"],
cache: false,
},
},
},
});Command: vp run gate:probe --no-cache
Observed
- Process exit code 1 (
0/2 successful). child:failexited 1.child:sentinelexited 137.sentinel-start.txtwas written.sentinel-done.txtwas not.- Wall time was about 147ms, not the sibling's 3 second sleep.
- The parent command did not run.
So a failing dependency does not only skip the parent. It SIGKILLs the sibling that had already started. A gate that fans out to many checks then hides every result that was in flight or not yet scheduled.
Expected
Either document and honor an option that runs every sibling to completion and still exits non-zero if any failed, or make that the default for dependsOn peers. Killing an in-flight sibling (exit 137) should not be the only behavior.
This matches an earlier measurement on 1.3.0 (vp run gate:lint stopped scheduling after the first red and killed in-flight tasks, exit 137). 1.4.0 still does it.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Activity
voidzero-bot commentedon Nov 3, 2026
vite-tasksnapshot tests already codify the current fast-fail behavior.vite-taskrunner, not a crash or data-loss bug. It mainly affects fan-out/gate-style task graphs that would benefit from a non-bailing option, but there is currently no such option.vp runcancels thefast_fail_tokenas soon as any leaf task exits non-zero. That token is wired intospawn.rsso every child process waits on it; when it fires, the runner callschild.start_kill(), which sendsSIGKILLand produces the observed exit 137 for the still-running sibling. The parent task is then skipped because the scheduler closes the semaphore on cancellation.I wasn't able to find a fix, but I identified some areas that may be relevant. The fast-fail logic lives in the upstream
vite-taskgit dependency (rev40cb9cac46bddbf8aa5ce5373df1a6a1980acc38), specificallycrates/vt/src/session/execute/scheduler.rs,crates/vt/src/session/execute/spawn.rs,crates/vt/src/session/mod.rs, and the CLI flags incrates/vt/src/cli/mod.rs. A proper fix would be to add a--continue/--no-bailflag, thread it throughPlanOptions/ExecutionContext, and only cancelfast_fail_tokenwhen that mode is enabled, while still exiting non-zero if any task failed. TheCargo.tomlrev forvite-taskwould then need to be bumped invite-plus.Full Triage Report
Triage Report: Issue #3323
Summary
vp runSIGKILLs an in-flight sibling task when a peerdependsOntask fails, instead of letting siblings run to completion and reporting all failures.Environment
vpversion: v1.4.0vite-plus: v1.4.0triagebot/fix-3323Reproduction
Created
/tmp/vite-plus-triage/gh-3323/reprowith the followingvite.config.ts:Command:
Result
Reproduced on current
main/triagebot/fix-3323.Output:
Exit code:
1vp run --last-details:Observations:
child:sentinelwas killed with exit code 137 (SIGKILL).sleep, confirming the sibling was terminated early.sentinel-start.txtnorsentinel-done.txtwas present after the run.gate:probe) did not run, which is expected because dependencies failed.Control case
Changed
child:failto exit 0 and re-ranvp run gate:probe --no-cache:03/3 successfulparent-ranwas printed.sentinel-start.txtandsentinel-done.txtwere written.sleep 3.This confirms the task configuration and commands work when no dependency fails, and the early termination of siblings is caused by the peer dependency failure.
Conclusion
The bug is reproducible.
vp runaggressively terminates in-flight sibling tasks when any peerdependsOntask fails, which prevents gate/fan-out tasks from collecting full results. The task runner lacks an option (or default behavior) that runs all siblings to completion while still exiting non-zero for failures.Diagnosis
Affected code path
vp runis handled by the Vite Task (vt) git dependency, not by code in the localvite-plusrepository. Routing in this repo sends the command intovthere:packages/cli/src/bin.ts: dispatches to the NAPIrun()function.packages/cli/binding/src/lib.rs:run()spawns the Rust worker and callscrate::cli::main(...).packages/cli/binding/src/cli/mod.rs: parsesCLIArgs::ViteTask(command)and callsexecute_vite_task_command(...), which callssession.main(command).await.The actual scheduling/spawning logic lives in the cargo git checkout of
vt:~/.cargo/git/checkouts/vite-task-*/<rev>/crates/vt/src/session/execute/scheduler.rs~/.cargo/git/checkouts/vite-task-*/<rev>/crates/vt/src/session/execute/spawn.rs~/.cargo/git/checkouts/vite-task-*/<rev>/crates/vt/src/session/mod.rs(token creation)~/.cargo/git/checkouts/vite-task-*/<rev>/crates/vt/src/cli/mod.rs(RunFlags/PlanOptions)Root cause
The task scheduler implements a hard-coded “fast-fail” strategy. Key points:
In
crates/vt/src/session/mod.rsaround lines 421–422 and 744–745, the session creates two cancellation tokens:fast_fail_token— cancelled when any task fails.cancel_token— a child offast_fail_token, cancelled on Ctrl-C (and inherited via the child relationship on fast-fail).In
crates/vt/src/session/execute/scheduler.rs(execute_leaf,execute_expanded_graph):execute_leafcallsself.fast_fail_token.cancel().cancelled()(the child token) in theFuturesUnorderedprocessing loop, closes the semaphore, and stops scheduling new tasks.In
crates/vt/src/session/execute/spawn.rs(spawn_tokio), thewaitfuture is wrapped as:The
cancellation_tokenpassed tospawn()isfast_fail_token. When it fires,child.start_kill()sends SIGKILL on Unix, producing exit code 137 (128 + SIGKILL 9). This is exactly whatchild:sentinelreports.There is no CLI flag, config option, or environment variable that disables fast-fail.
RunFlagsexposes--ignore-depends-on,--parallel,--no-cache,--cache,--concurrency-limit, and--log, but nothing like--no-bail/--continue.Why this matches the observed behavior
fast_fail_token.cancel_tokenis a child offast_fail_token, the whole graph becomes “cancelled”.start_kill().Suggested fix approach
Because the failing code is in the external
vite-taskrepository, the fix must be made there and theCargo.tomlrev bumped in this repo.Proposed change:
RunFlagsoption such as--continue/--no-bail(or make non-bailing the default fordependsOnpeers).ResolvedRunCommand::into_query_plan_requestinto a newPlanOptionsfield, e.g.bail: bool.Session::execute_graphandExecutionContext.execute_leaf, only cancelfast_fail_tokenwhenbailistrue. Ifbailisfalse, record the failure but let the scheduler continue scheduling ready dependents and letspawn.rskeep waiting on in-flight children.vp run --helpoutput (RustRunFlagsdoc strings; JS help is generated/derived from the same clap definitions or mirrored inpackages/cli/src/help.ts).docs/config/run.mdif it is exposed as config, or in the CLI help / user docs if CLI-only.Edge cases to consider:
--no-bail, Ctrl-C should still propagate throughcancel_tokenand kill children.vp runinvocations inside task scripts: the flag should propagate viaPlanOptionsto nested levels.job.terminate(); with--no-bailwe should avoid that path but still allow normal cleanup.Regression / version note
The issue was observed on
vp v1.4.0and was already present onv1.3.0. The currenttriagebot/fix-3323checkout (vite-plus 1.4.0) uses the same hard-coded fast-fail code, so release history is consistent with this root cause.Verification
Claim
Reporter observed: when one
dependsOnpeer fails,vp runSIGKILLs the in-flight sibling (child:sentinelexit 137) and reports0/2 successful. The reporter expects either a documented option to let every sibling finish (and exit non-zero), or that behavior as the default.Evidence
Product documentation.
docs/config/run.mddescribesdependsOnas "tasks that must complete successfully before this one starts" but does not say what happens to concurrent siblings when one fails. The guide atdocs/guide/run.mdalso does not mention fast-fail behavior.Vite Task cancellation documentation (
vite-taskgit checkoutdocs/cancellation.md, upstream) explicitly documents the current behavior:This confirms the
child:sentinelSIGKILL is the intended fast-fail mechanism.Source code comments. In the
vtscheduler.rs:And
spawn.rsspawn_tokio()raceschild.wait()against the cancellation token and callschild.start_kill()when it fires.Existing tests / CLI snapshots in the
vtrepo codify fast-fail:crates/vt_bin/tests/e2e_snapshots/fixtures/concurrent_execution/snapshots/failure_kills_concurrent_tasks.md: explicitly asserts "When one concurrent task fails, the sibling running under inherited stdio must be cancelled."crates/vt_bin/tests/e2e_snapshots/fixtures/exit_codes/snapshots/task_failure_fast_fails_remaining_tasks.md: asserts a failing task under-rfast-fails the run and skips remaining packages.crates/vt_bin/tests/e2e_snapshots/fixtures/exit_codes/snapshots/dependency_failure_fast_fails_dependents.md: asserts dependents are skipped when a dependency fails.Prior release / change history. Git commit
45b667ceinvite-task("fix(cache): stop remote cache requests on Ctrl-C and fast-fail") intentionally kept fast-fail semantics and shortened the comment to point tospawn.rsfor killing. Git commit history shows fast-fail has been the intended design, not an accidental regression.GitHub search. Searching the
voidzero-dev/vite-plusrepo forno-bail,continue,fast fail, andexit 137found no earlier proposals for a non-bailing mode; issue vp run kills in-flight sibling tasks when one dependsOn task fails #3323 is the only relevant one.Verdict
This is intended behavior. The task runner is explicitly designed to fast-fail on the first non-zero task exit, killing in-flight siblings and skipping not-yet-scheduled dependents. The reporter's request is effectively a feature request for a
--no-bail/--continue-style option or a change to the default fast-fail policy, rather than a bug in the implemented behavior.Confidence
High. Intent is documented in upstream
docs/cancellation.md, enforced by snapshot tests, and explicit in both scheduler comments and commit history.This report was made by an LLM. The analysis may be wrong, and the potential fix might not work, but is intended as a starting point for exploring the issue.
n0mer commentedon Nov 3, 2026
Closing this. It was opened in error. We are not asking voidzero to track it.