Skip to content

File changed on disk with a content-mapped or .d.ts extension never triggers workspace/diagnostic/refresh #64943

Open

Description

@mrlubos

🔎 Search Terms

"content mapper", "contentMappers", "workspace/diagnostic/refresh", "didChangeWatchedFiles", "isRelevantExtension", "stale diagnostics", "restart TS server", ".d.ts"

🕗 Version & Regression Information

⏯ Playground Link

No response

💻 Code

Repro: https://github.com/mrlubos/ts-content-mapper-refresh (npm install && npm run repro)

// tsconfig.json
{ "compilerOptions": { "module": "nodenext", "strict": true, "noEmit": true },
  "contentMappers": [{ "package": "toy-mapper", "extensions": [".data"] }] }
// index.ts. toy-mapper turns each `name: type` line of shape.data into a member of `Data`.
import type { Dep } from './dep.js';
import type { Data } from './shape.data';
declare const dep: Dep;
declare const data: Data;
export const fromTs = dep.age;     // error until `age` is added to dep.ts
export const fromData = data.age;  // error until `age: number` is added to shape.data

🙁 Actual behavior

After shape.data changes on disk (written by another process, with the editor sending workspace/didChangeWatchedFiles), the server never sends workspace/diagnostic/refresh. In VS Code the error on data.age stays until "TypeScript: Restart TS Server". The server already has the right answer: a textDocument/diagnostic request made by hand returns no errors. npm run repro drives tsc --lsp as VS Code does and prints:

  1. dep.ts changed on disk, refresh requests: 1
  2. shape.data changed on disk, refresh requests: 0
    errors when pulled by hand: []
  3. shape.data edited while open, refresh requests: 1

🙂 Expected behavior

A change on disk to a file a registered content mapper handles should refresh diagnostics the way a change to a .ts file does, since it changes the program. This matters most when a tool regenerates the mapped file, for example a dev server writing an API description on each reload, because the editor never has that file open.

Additional information about the issue

path.Extension() returns only the extensions TypeScript reads itself. For shape.data it returns "", so the path is treated as a possible directory: DirectoryExists is false and the change is dropped. The check against the extensions a project's contentMappers register is in the else branch, which a mapped extension never reaches.

The same change breaks .d.ts files: path.Extension() returns .d.ts, which isRelevantExtension does not list, so a declaration file changed on disk does not refresh diagnostics either.

A workaround for mapped files is to keep the file open in an editor tab, so VS Code reloads it and sends didChange.

Activity

  1. changed the title [-]Content-mapped file changed on disk never triggers workspace/diagnostic/refresh[/-] [+]File changed on disk with a content-mapped or .d.ts extension never triggers workspace/diagnostic/refresh[/+] on Oct 23, 2026
  2. changed the title [-]File changed on disk with a content-mapped or .d.ts extension never triggers workspace/diagnostic/refresh[/-] [+]File changed on disk with a content-mapped or `.d.ts` extension never triggers workspace/diagnostic/refresh[/+] on Oct 23, 2026
  3. added a commit that references this issue on Oct 23, 2026
    f8edd05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions