-
-
Notifications
You must be signed in to change notification settings - Fork 942
linter: panic with WouldBlock in oxc_diagnostics::service on large projects #20239
Copy link
Copy link
Closed
Closed
Copy link
Description
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-awareWhat does your config file look like?
(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-awareenabled (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.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Type
Fields
Give feedbackPriority
None yet
{ "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 ] }