Summary
vp staged --no-concurrent never executes any task. Depending on the runtime
context, the process either hangs indefinitely or exits with code 13 and a
cryptic unsettled top-level await warning — in both cases with no output
indicating that nothing ran. In a pre-commit hook, the exit-13 variant blocks
the commit without explanation.
Reproduction
mkdir repro && cd repro
git init
cat > vite.config.ts <<'EOF'
export default { staged: { '*.txt': 'echo linted' } }
EOF
echo hi > a.txt
git add -A .
vp staged --no-concurrent
Expected: serial execution (same as --concurrent false).
Actual: tasks never start; the run hangs or exits 13.
Root cause
packages/cli/src/staged/bin.ts parses argv with mri, with concurrent
declared in the string list. mri returns a boolean false for
--no-<flag> regardless of the string list:
mri(['--no-concurrent'], { string: ['concurrent'] }) // → { concurrent: false }
The strict comparison val === 'false' only matches the string spelling, so
the boolean falls through to the else branch, where Number(false) coerces
to 0. lint-staged's task queue (listr2 Concurrency) never starts a task
when the concurrency limit is 0 (this.count < this.concurrency is 0 < 0),
so the run deadlocks without output.
Note this was an accident, not a design choice: serial mode via false has
been documented in --help since the initial commit (#674), and the parsing
mirrors lint-staged's own CLI (JSON.parse of the value). The --no-
spelling was simply mishandled from day one.
Related
The same mri quirk leaks boolean false into the other string options in the
same file, so these also misbehave (exit 1 with confusing errors):
vp staged --no-cwd → Failed to load vite.config: paths[0] argument must be of type string. Received type boolean (false)
vp staged --no-diff → Failed to get staged files! (and the backup stash is skipped)
Explicit -p 0 / --concurrent=0 reach the same concurrency-0 deadlock via
the else branch, since 0 passes the Number.isNaN(num) || val === ''
guard.
Environment
Summary
vp staged --no-concurrentnever executes any task. Depending on the runtimecontext, the process either hangs indefinitely or exits with code 13 and a
cryptic
unsettled top-level awaitwarning — in both cases with no outputindicating that nothing ran. In a pre-commit hook, the exit-13 variant blocks
the commit without explanation.
Reproduction
Expected: serial execution (same as
--concurrent false).Actual: tasks never start; the run hangs or exits 13.
Root cause
packages/cli/src/staged/bin.tsparses argv with mri, withconcurrentdeclared in the
stringlist. mri returns a booleanfalsefor--no-<flag>regardless of thestringlist:The strict comparison
val === 'false'only matches the string spelling, sothe boolean falls through to the
elsebranch, whereNumber(false)coercesto
0. lint-staged's task queue (listr2Concurrency) never starts a taskwhen the concurrency limit is 0 (
this.count < this.concurrencyis0 < 0),so the run deadlocks without output.
Note this was an accident, not a design choice: serial mode via
falsehasbeen documented in
--helpsince the initial commit (#674), and the parsingmirrors lint-staged's own CLI (
JSON.parseof the value). The--no-spelling was simply mishandled from day one.
Related
The same mri quirk leaks boolean
falseinto the other string options in thesame file, so these also misbehave (exit 1 with confusing errors):
vp staged --no-cwd→Failed to load vite.config: paths[0] argument must be of type string. Received type boolean (false)vp staged --no-diff→Failed to get staged files!(and the backup stash is skipped)Explicit
-p 0/--concurrent=0reach the same concurrency-0 deadlock viathe
elsebranch, since0passes theNumber.isNaN(num) || val === ''guard.
Environment
vp stagedshipped in feat(hooks): add built-in pre-commit hook viavp config+vp staged#674)