Fix: Oxlint Not Working — .oxlintrc.json Config, Rule Mapping, TypeScript, and ESLint Coexistence
Part of: JavaScript & TypeScript Errors
Quick Answer
How to fix Oxlint errors — .oxlintrc.json not loaded, rules not matching ESLint output, TypeScript files not linted, plugin-react/typescript wiring, IDE extension setup, and running alongside ESLint.
The Error
You install Oxlint and the config file is silently ignored:
$ oxlint
# Uses defaults, ignores your .oxlintrc.json with custom rules.Or rules you turned off keep firing:
// .oxlintrc.json
{
"rules": {
"no-unused-vars": "off"
}
}$ oxlint
src/util.ts:5:7
✗ no-unused-vars: 'x' is declared but never usedOr TypeScript-specific files give wrong results:
$ oxlint src/
# Only lints .js files, skips .ts entirely.Or you can’t tell what rules differ between Oxlint and ESLint:
ESLint passes. Oxlint fails on the same file.Why This Happens
Oxlint is a Rust-based linter from the Oxc project. It’s positioned as a fast, drop-in subset of ESLint — it implements the most popular ESLint rules natively in Rust, but with these caveats:
- Not every ESLint rule exists. Oxlint has hundreds of rules but not all of ESLint’s 300+ plugins. Missing rules don’t error — they just don’t run.
- Config syntax is its own.
.oxlintrc.jsonis similar to.eslintrc.jsonbut not identical. ESLint flat config (eslint.config.js) isn’t directly compatible. - Plugin namespacing differs. Oxlint groups rules by plugin (
typescript,react,jest, etc.) but uses its own internal names.@typescript-eslint/no-unused-varsbecomestypescript/no-unused-vars. - Designed to run alongside ESLint, not replace it. The recommended workflow is Oxlint as a fast first pass + ESLint for rules Oxlint doesn’t support (yet).
The deeper reason rule names diverge is architectural. ESLint’s rules live in user-installable npm packages that each contribute their own namespace; Oxlint’s rules are compiled into the binary and grouped by the original ESLint plugin they emulate. Oxlint had to pick a canonical name per rule, and it dropped the @typescript-eslint/ and eslint-plugin- prefixes for ergonomics. That choice keeps the config file shorter but breaks copy-paste from .eslintrc files. The same rule names also appear in editor diagnostics, so a search for “how do I disable this Oxlint error” frequently lands on ESLint documentation that no longer applies.
A second source of confusion is the speed of Oxlint’s iteration. Through 2024 and 2025, Oxlint shipped new plugin support, type-aware rules, and config format changes almost monthly. A .oxlintrc.json written for 0.4 may emit warnings on 0.10 about deprecated fields; a snippet from a blog post written six months ago may reference a rule that has since been renamed. Pinning the version in package.json and running oxlint --print-config are the two habits that prevent “it worked yesterday” debugging sessions.
Finally, Oxlint’s silent skipping is intentional. ESLint errors loudly on unknown rules, which made adopting it across a monorepo painful — every team had to agree on the plugin set or builds broke. Oxlint chose the opposite default: unknown rules are no-ops. That’s friendly for adoption but lethal for confidence. The mitigation is to enable --deny-warnings in CI and to use --print-config in a pre-commit hook so the team knows exactly what is and isn’t being checked.
Fix 1: Place .oxlintrc.json in the Right Location
Oxlint looks for .oxlintrc.json (or .oxlintrc) in the directory you run from and walks up:
// .oxlintrc.json — at project root
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"rules": {
"no-unused-vars": "off",
"no-console": "warn",
"typescript/no-explicit-any": "error"
},
"ignorePatterns": [
"dist/**",
"node_modules/**"
],
"env": {
"browser": true,
"node": true,
"es2024": true
}
}Verify Oxlint picks up the config:
oxlint --print-configThis prints the merged config. If your custom rules don’t appear, the file isn’t being loaded — check the filename (must be .oxlintrc.json, not oxlintrc.json) and that you’re running from a directory under it.
Pro Tip: Pin the schema reference via $schema for editor autocomplete. The schema lives in node_modules/oxlint/configuration_schema.json after install.
Fix 2: Use Oxlint’s Plugin-Prefixed Rule Names
Oxlint groups rules by plugin. To target plugin rules:
{
"plugins": ["typescript", "react", "jest", "unicorn"],
"rules": {
"typescript/no-explicit-any": "error",
"typescript/no-unused-vars": "off",
"react/jsx-key": "error",
"react/no-array-index-key": "warn",
"jest/no-disabled-tests": "warn",
"unicorn/prefer-set-has": "error"
}
}Without "plugins" listing, plugin rules don’t run — even if you reference them in rules. The plugins enable the rule set; rules overrides severity.
For ESLint users migrating, the mapping is mostly:
| ESLint rule | Oxlint rule |
|---|---|
@typescript-eslint/no-explicit-any | typescript/no-explicit-any |
react-hooks/rules-of-hooks | react/rules-of-hooks |
import/no-cycle | import/no-cycle |
jest/no-disabled-tests | jest/no-disabled-tests |
The prefix follows the plugin’s “short name.” Run oxlint --help to see the available flags for listing rules in your installed version — recent releases support a flag to print the full rules table.
Common Mistake: Copying ESLint config verbatim. @typescript-eslint/* doesn’t work — drop the @typescript-eslint/ prefix and use typescript/.
Fix 3: Lint TypeScript Explicitly
Oxlint auto-detects .ts, .tsx, .cts, .mts if you pass a directory:
oxlint src/ # Lints all .js, .ts, .jsx, .tsx filesIf you pass --ext flags:
oxlint --ext .ts,.tsx src/Without the right extension list, Oxlint silently skips files.
For TS-specific rules (the typescript/* namespace), Oxlint doesn’t need type information for most rules — it works on the AST alone. A handful of rules that do need types (e.g. type-aware unused checks) are explicitly marked in the docs.
{
"plugins": ["typescript"],
"rules": {
"typescript/no-explicit-any": "error",
"typescript/consistent-type-imports": "warn",
"typescript/no-non-null-assertion": "warn"
}
}Fix 4: Categories Pre-Configured Sets
Oxlint exposes rule categories you can opt into wholesale:
{
"categories": {
"correctness": "error",
"suspicious": "warn",
"perf": "warn",
"pedantic": "off",
"style": "off",
"restriction": "off"
}
}Or via CLI:
oxlint -W perf -W suspicious src/correctness is on by default. The other categories opt-in based on how strict you want to be:
correctness— likely bugs (unused vars, unreachable code, no-debugger).suspicious— code that’s probably wrong but not certainly.perf— performance smells (for-eachon large arrays, etc.).pedantic— stricter style/safety guidance.style— pure formatting/style.restriction— bans on specific patterns (no-console, no-debugger).
For a balanced default, enable correctness + suspicious + perf. Add pedantic once the easier ones are clean.
Fix 5: Run Alongside ESLint, Not Instead
The most pragmatic adoption pattern: Oxlint runs first (catches the common issues fast), then ESLint for plugin rules Oxlint hasn’t ported:
{
"scripts": {
"lint": "oxlint && eslint .",
"lint:fast": "oxlint",
"lint:full": "eslint ."
}
}In eslint.config.js, exclude rules that Oxlint already covers to avoid double-reporting:
import oxlint from "eslint-plugin-oxlint";
export default [
// ... your other configs
// This must be the last config in the chain.
...oxlint.configs["flat/recommended"],
];eslint-plugin-oxlint disables ESLint rules that Oxlint already implements — your ESLint pass becomes the “rules Oxlint doesn’t support yet” pass.
Pro Tip: Run Oxlint in pre-commit hooks and CI’s first job; run ESLint in a separate (slower) CI job. Oxlint catches 90% of issues in milliseconds.
Fix 6: IDE Integration
For VS Code:
# Install the Oxc extension from the marketplace:
# "Oxc" by oxc.rsThe extension uses Oxlint’s LSP for in-editor lints. Configure in .vscode/settings.json:
{
"oxc.enable": true,
"oxc.lint.run": "onType", // or "onSave"
"oxc.path": "./node_modules/.bin/oxlint"
}For JetBrains IDEs: there’s an Oxc plugin under development; until then, run Oxlint via a file watcher.
For Neovim: use nvim-lspconfig with the Oxc LSP:
require("lspconfig").oxc.setup({})Common Mistake: Running both ESLint and Oxlint extensions in the IDE at full strength. You’ll see duplicate squiggles. Disable rules Oxlint covers in your ESLint config (see Fix 5).
Fix 7: Ignore Files
Oxlint supports ignorePatterns in .oxlintrc.json and a separate .oxlintignore:
{
"ignorePatterns": [
"dist/**",
"build/**",
"**/*.generated.ts",
"vendor/**"
]
}Patterns use gitignore-style globs. For more complex ignore logic:
# .oxlintignore
dist/
build/
coverage/
**/*.min.js
**/*.generated.*Oxlint also respects .gitignore by default (don’t lint what git ignores). If you need to lint something .gitignored, override via the CLI:
oxlint --no-ignore <file>Fix 8: Performance Tuning
Oxlint is fast by default. For monorepos with hundreds of thousands of files:
oxlint --threads 8 src/--threads defaults to the CPU count. Manually capping it helps when CI machines have ulimit issues.
For caching across CI runs (Oxlint doesn’t natively cache yet — but you can scope):
# Only lint files changed since main:
oxlint $(git diff --name-only origin/main...HEAD | grep -E '\.(ts|tsx|js|jsx)$')Pro Tip: Oxlint typically runs 50-100x faster than ESLint on the same files. If your Oxlint run still feels slow, you’re probably linting too many files — check ignorePatterns.
Version History and Tooling Context
Oxlint moves fast — the table below covers the milestones that matter when you’re reading docs, copying configs, or pinning versions:
- Oxlint 0.1 (October 2023) shipped the first public release: roughly 100 ported ESLint rules, no plugin namespacing, JSON-only config. Configs from this era look surprisingly different from what’s current.
- Oxlint 0.2 added the type-aware preview. A subset of
typescript/*rules began using TypeScript-style type information, though the API for enabling them was experimental. - Oxlint 0.4 (July 2024) introduced the plugin model and the
pluginsfield in.oxlintrc.json. This is whentypescript/no-explicit-anyandreact/jsx-keybecame the canonical naming. Almost all current tutorials assume 0.4 or later. - Oxlint 0.6–0.9 added React, Jest, Unicorn, JSDoc, and N (node) plugin families and stabilized the categories system (
correctness,suspicious,perf,pedantic,style,restriction). The--threadsflag landed here as well. - Oxlint 0.10+ improved ESLint compatibility: more
// eslint-disable-next-linedirectives are read, moreeslint-plugin-*rule mappings are recognized, and the LSP for editor integration matured. Theeslint-plugin-oxlintpackage became stable around this point as the canonical way to disable doubled-up ESLint rules. - Oxlint 0.13+ introduced richer JSONC support in config files and tightened the schema (extra fields now warn). If you upgrade and suddenly see warnings about unknown config keys, this is why.
Compared to alternatives: Biome (formerly Rome) is also a Rust-based linter and formatter, but its rule set was reimagined from scratch rather than ported from ESLint, so it’s less drop-in but more cohesive. ESLint 9 with flat config is still the most flexible option — every plugin ever written for it works — but it’s an order of magnitude slower than Oxlint. Quick-Lint-JS focuses on real-time editor integration but doesn’t aim for the breadth of either tool. The practical 2026 pattern is: Oxlint as the fast gate in pre-commit and CI, ESLint or Biome for rules Oxlint hasn’t ported, and eslint-plugin-oxlint keeping the two in sync so nobody flags the same issue twice.
Still Not Working?
A few less-obvious failures:
- Rule severity says
"warn"but CI fails. Some tools (oxlint --deny-warningsor--max-warnings 0) escalate warnings to failures. Check your CI command. .oxlintrc.jsonhas comments and fails to parse. Standard JSON doesn’t allow comments. Use.oxlintrc.jsonwith no comments, or.oxlintrc.jsoncif your version supports JSONC.- Auto-fix not working for some rules. Only a subset of rules are auto-fixable. Use
oxlint --fixto apply the fixable ones; the unfixable ones still need manual edits. - Disabling a rule per-line with
// eslint-disable-linedoesn’t work. Oxlint uses its own directive:// oxlint-disable-next-line rule-name. Or use ESLint-compatible directives (Oxlint reads// eslint-disable-next-linetoo as of recent versions). - Plugin not recognized. Check Oxlint’s release notes — plugin support is being added incrementally. A rule from
eslint-plugin-importmay or may not be in your Oxlint version. - Different output between local and CI. Different Oxlint versions. Pin in
package.json:"oxlint": "0.10.0"(exact), not^0.10.0. - Lint fails on JSX without React import. Oxlint’s
react/react-in-jsx-scopedefaults assume classic JSX runtime. Disable it for projects on the automatic runtime:"react/react-in-jsx-scope": "off". - Globals not recognized.
globalsin config or/* global Foo */directives. Add browser/node globals viaenv:
{
"env": {
"browser": true,
"node": true
},
"globals": {
"MY_CUSTOM_GLOBAL": "readonly"
}
}oxlintexits 0 but Biome flags the same file. The two tools share rule names but apply different defaults. Set a category ("correctness": "error") to force the rule on rather than relying on Biome-style implicit defaults.- Editor shows different errors than CLI. The Oxc LSP and the
oxlintCLI sometimes resolve different.oxlintrc.jsonfiles when you have nested configs. Runoxlint --print-config <file>from the project root to see which config the CLI uses, then point the editor at the same one viaoxc.path. oxlint --fixrewrites code your formatter then changes back. Oxlint’s fixer and Prettier disagree on whitespace in a handful of cases (trailing commas, JSX whitespace). Run Prettier afteroxlint --fixin yourpackage.jsonscript, and addlint:fix && formatas a single command so neither tool is the last writer alone.- Rule disabled in config still fires in CI. Some monorepo configurations have multiple
.oxlintrc.jsonfiles; the one nearest the file being linted wins. Move overrides to the root or useoverridesarrays to scope them correctly.
For related linting, formatting, and bundler tooling issues, see Biome not working, ESLint config not working, ESLint parsing error unexpected token, and ESLint no-unused-vars false positive.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: ESLint Flat Config Not Working — eslint.config.js, ignores, Plugins, and Migration
How to fix ESLint flat config errors — eslint.config.js not found, .eslintrc.json ignored after upgrade, ignores replacing .eslintignore, plugin object form, typescript-eslint integration, monorepo configs, and ESLINT_USE_FLAT_CONFIG.
Fix: ESLint import/no-unresolved Error (Module Exists but ESLint Can't Find It)
How to fix ESLint's import/no-unresolved errors when modules actually resolve correctly — configure eslint-import-resolver-typescript, fix path alias settings, and handle node_modules that ESLint cannot find.
Fix: Clack Not Working — Prompts Not Displaying, Spinners Stuck, or Cancel Not Handled
How to fix @clack/prompts issues — interactive CLI prompts, spinners, multi-select, confirm dialogs, grouped tasks, cancellation handling, and building CLI tools with beautiful output.
Fix: Sharp Not Working — Installation Failing, Image Not Processing, or Build Errors on Deploy
How to fix Sharp image processing issues — native binary installation, resize and convert operations, Next.js image optimization, Docker setup, serverless deployment, and common platform errors.