Skip to content

linter: oxlint.config.ts changes not reflected after didChangeWatchedFiles (LSP config hot-reload) #19526

@thkang-commits

Description

@thkang-commits

What version of Oxlint are you using?

1.48.0

What command did you run?

oxlint --lsp

What does your .oxlintrc.json config file look like?

  // oxlint.config.ts
  import jestDom from 'eslint-plugin-jest-dom';
  import { defineConfig } from 'oxlint';

  const jestDomRules = jestDom.configs['flat/recommended'].rules;

  export default defineConfig({
    plugins: ['typescript'],
    categories: { correctness: 'error' },
    overrides: [
      {
        files: ['*.spec.ts', '*.spec.tsx', '*.test.ts', '*.test.tsx'],
        jsPlugins: ['eslint-plugin-jest-dom'],
        rules: { ...jestDomRules },
      },
    ],
  });

What happened?

When oxlint.config.ts is modified and saved, the LSP server receives the workspace/didChangeWatchedFiles notification and re-lints all open files, but the updated config is not applied — diagnostics remain identical to those from the previous config state.

For example, commenting out the jest-dom override should remove all jest-dom/* diagnostics from test files, but they persist until a full LSP restart.

Steps to Reproduce

  1. Start oxlint --lsp with the config above — jest-dom diagnostics appear on test files ✅
  2. Comment out the jest-dom override in oxlint.config.ts and save
  3. Expected: jest-dom diagnostics disappear from test files
  4. Actual: jest-dom diagnostics remain unchanged

A full process restart (e.g. :LspRestart in Neovim(lazy.vim)) correctly picks up the config changes.

LSP Log Evidence

The protocol-level communication is all correct:

  1. Watcher registration — server sends client/registerCapability with **/oxlint.config.ts
    pattern ✅
  2. File change notification — client sends workspace/didChangeWatchedFiles on save ✅
  3. Re-lint + publishDiagnostics — server responds with diagnostics ✅
  4. But diagnostics use the OLD config ❌ — jest-dom rules still fire after being removed from
    config

Suspected Cause

handle_watched_file_change in server_linter.rs creates a new ServerLinter via builder.build_boxed(), but the TypeScript config evaluation result (via jiti) appears to be cached, so the new linter instance reads the stale compiled config instead of re-evaluating oxlint.config.ts.

Environment

  • Editor: Neovim 0.11.6
  • OS: macOS (darwin-arm64)

Workaround

Restart the LSP server when config files change (e.g. via BufWritePost autocmd).

Disclaimer

I investigated this issue with significant help from Claude Code (AI coding assistant) for analyzing Neovim LSP internals and oxlint source code. While the LSP log evidence is from my actual environment, the root cause analysis (jiti caching in handle_watched_file_change) is based on AI-assisted source code reading and may not be entirely accurate. Corrections are welcome.

Metadata

Metadata

Assignees

Labels

A-editorArea - Editor and Language ServerA-linterArea - Linter

Type

Priority

None yet

Effort

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions