Skip to content

vp check panics on EAGAIN while replaying large lint diagnostics #2165

Description

@hyoban

Describe the bug

vp check panics while replaying a large captured Oxlint diagnostic block when stdout temporarily returns EAGAIN / WouldBlock.

Expected behavior: vp check should handle stdout backpressure without panicking or truncating diagnostics. If output cannot be written, it should retry appropriately or return a regular I/O error.

Actual behavior: the process prints the warning heading, invokes the Vite+ panic hook, drains only part of the buffered diagnostics, and exits with code 129. The following pnpm lint:eslint command is never executed.

This occurs in a public GitHub Actions job, so it is not specific to a local terminal or Codex output pipe.

Reproduction

https://github.com/langgenius/dify/actions/runs/29259173815/job/86847662089

The failing source revision is:

langgenius/dify@00196da

Steps to reproduce

  1. Check out the failing revision:

    git clone https://github.com/langgenius/dify.git
    cd dify
    git checkout 00196da9c166c2191fd33937afe3b01369a893c1
  2. Install Vite+ 0.2.4 dependencies and run the repository check under GitHub Actions or another stdout consumer that can apply non-blocking backpressure:

    vp install
    pnpm -w check
  3. The package script runs:

    vp check && pnpm lint:eslint
  4. Formatting succeeds for 8,557 files. After linting finishes, vp check starts replaying the captured diagnostics and panics with os error 11.

The trigger is the large diagnostic set: this revision produces approximately 2,426 warnings.

A follow-up commit replaced vp check with vp fmt --check && vp lint --quiet:

langgenius/dify@0178010

The corresponding job succeeds on the same runner type and reports all 2,426 warnings and 0 errors:

https://github.com/langgenius/dify/actions/runs/29259903686/job/86850424110

Locally, with the same project and tool versions:

  • vp check reproducibly panics when writing to a backpressured output pipe.
  • vp lint successfully emits the same 2,427 diagnostics.
  • vp check >/dev/null completes successfully.

This differential points to the vp check capture/analyze/replay path rather than Oxlint itself.

System Info

$ vp env current
Environment:
  Version       22.23.1
  Source        devEngines.runtime
  Source Path   /path/to/dify/package.json
  Project Root  /path/to/dify

Tool Paths:
  node  ~/.vite-plus/js_runtime/node/22.23.1/bin/node
  npm   ~/.vite-plus/js_runtime/node/22.23.1/bin/npm
  npx   ~/.vite-plus/js_runtime/node/22.23.1/bin/npx

Package Manager:
  Name          pnpm
  Version       11.10.0
  Source        packageManager
  Source Path   /path/to/dify/package.json
  Project Root  /path/to/dify
  Bin Path      ~/.vite-plus/package_manager/pnpm/11.10.0/pnpm/bin/pnpm

$ vp --version
vp v0.2.4

Local vite-plus:
  vite-plus  v0.2.4

Tools:
  vite             v8.1.3
  rolldown         v1.1.4
  vitest           v4.1.10
  oxfmt            v0.57.0
  oxlint           v1.72.0
  oxlint-tsgolint  v0.24.0
  tsdown           v0.22.3

Environment:
  Package manager  pnpm v11.10.0
  Node.js          v22.23.1 (devEngines.runtime)

The public CI reproduction runs on depot-ubuntu-24.04-4. A local reproduction also occurs on macOS, where the equivalent error is os error 35.

Used Package Manager

pnpm

Logs

$ vp check && pnpm lint:eslint
pass: All 8557 files are correctly formatted (4122ms, 4 threads)
warn: Lint or type warnings found
Vite+ panicked. This is a bug in Vite+, not your code.

thread '<unnamed>' (3117) panicked at library/std/src/io/stdio.rs:1166:9:
failed printing to stdout: Resource temporarily unavailable (os error 11)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

[diagnostics continue briefly, then truncate]

ELIFECYCLE Command failed with exit code 129.

Initial analysis

In Vite+ 0.2.4, vp check forces Oxlint's default reporter and captures its output before analyzing and replaying it:

https://github.com/voidzero-dev/vite-plus/blob/v0.2.4/packages/cli/binding/src/check/mod.rs#L156-L180

The failure path then calls print_stdout_block followed by print_summary_line:

https://github.com/voidzero-dev/vite-plus/blob/v0.2.4/packages/cli/binding/src/check/mod.rs#L199-L213

print_stdout_block currently discards both write_all results:

https://github.com/voidzero-dev/vite-plus/blob/v0.2.4/packages/cli/binding/src/check/analysis.rs#L130-L142

let _ = stdout.write_all(trimmed.as_bytes());
let _ = stdout.write_all(b"\n");

The same code is still present on main at the time of filing. A likely sequence is:

  1. Replaying the large captured diagnostic block fills the non-blocking stdout pipe.
  2. write_all returns WouldBlock, but the error is discarded.
  3. The following summary/output helper prints while stdout is still unavailable and panics through Rust's standard printing path.

This is related to #1285 because that report contains the same stdout panic signature. However, #1285 addressed the misleading Rolldown panic hook attribution. The underlying EAGAIN handling and diagnostic truncation remain reproducible in Vite+ 0.2.4 and on the current main implementation.

Validations

  • Read the Contributing Guidelines.
  • Checked that there is not already an issue tracking the underlying vp check stdout/backpressure bug.
  • Confirmed this is a Vite+ issue rather than an upstream Vite, Vitest, tsdown, Rolldown, or Oxc issue through the vp check versus vp lint differential.
  • Provided a deterministic, publicly runnable reproduction. The large diagnostic set is part of the trigger.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Fields

Priority

None yet

Effort

None yet

Target date

None yet

Start date

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions