Skip to content

linter: panic with WouldBlock in oxc_diagnostics::service on large projects #20239

@beorn

Description

@beorn

What version of Oxlint are you using?

1.53.0 (also reproduced on 1.52.0)

What command did you run?

find apps packages infra vendor \
  -path '*/node_modules' -prune -o -path '*/dist' -prune -o \
  \( -name '*.ts' -o -name '*.tsx' \) -print \
  | xargs oxlint -c oxlint.config.json --type-aware

What does your config file look like?

{
  "plugins": ["typescript", "promise"],
  "jsPlugins": ["oxlint-plugin-complexity"],
  "categories": { "correctness": "off" },
  "rules": {
    "complexity/complexity": ["warn", { "cyclomatic": 30, "cognitive": 30 }],
    "@typescript-eslint/prefer-optional-chain": "warn",
    "@typescript-eslint/no-floating-promises": "error",
    "@typescript-eslint/no-misused-promises": "error",
    // ... ~40 more rules, mostly typescript-eslint + promise
  },
  "overrides": [
    // 5 override blocks for vendor, test, and app files
  ]
}

(Full config is 232 lines — happy to share if needed)

What happened?

oxlint panics when linting ~1312 files that produce ~365 warnings. The panic is 100% reproducible.

Error output

thread 'tokio-rt-worker' panicked at crates/oxc_diagnostics/src/service.rs:213:26:
called `Result::unwrap()` on an `Err` value: Os { code: 35, kind: WouldBlock, message: "Resource temporarily unavailable" }

Root cause

check_for_writer_error in service.rs handles Interrupted and BrokenPipe but not WouldBlock. When diagnostic output volume is high enough (~365 warnings), stdout write returns WouldBlock (errno 35 / EAGAIN on macOS), and the .unwrap() panics.

fn check_for_writer_error(error: std::io::Error) -> Result<(), std::io::Error> {
    if matches!(error.kind(), ErrorKind::Interrupted | ErrorKind::BrokenPipe) {
        Ok(())
    } else {
        Err(error)  // WouldBlock falls through → .unwrap() panics
    }
}

Workarounds attempted

Workaround Result
--threads 1 Still crashes
xargs -n 400 (batching) Still crashes
Pipe through cat Still crashes
Direct args (no xargs) Still crashes
--quiet Works (reduces output volume)
Redirect to temp file (> /tmp/out 2>&1) Works

Environment

  • macOS 15.4 (Darwin 25.2.0), Apple Silicon
  • 1312 TypeScript files, 47 rules, 10 threads
  • --type-aware enabled (but also crashes without it)

Suggested fix

Add WouldBlock handling to check_for_writer_error — ideally with a retry loop rather than silently dropping the output:

fn check_for_writer_error(error: std::io::Error) -> Result<(), std::io::Error> {
    if matches!(error.kind(), ErrorKind::Interrupted | ErrorKind::BrokenPipe | ErrorKind::WouldBlock) {
        Ok(())
    } else {
        Err(error)
    }
}

Or better, retry the write on WouldBlock/Interrupted instead of silently dropping.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Priority

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions