Skip to content

A new module written by AFT stays 'Cannot find module' in TypeScript diagnostics: AFT writes send no Created watched-file event #1165

Closed

Description

@iceteaSA

Problem

When AFT's own write (or patch) creates a new TypeScript module, a file that imports it continues to report Cannot find module from the TypeScript server. The module is on disk and tsc passes. The same file created by a different program resolves after a few seconds.

Steps to reproduce (aft 0.62.0 module, TypeScript 6.0.3 through typescript-language-server)

A package with tsconfig.json (moduleResolution: "Bundler", allowImportingTsExtensions), local node_modules/typescript, and lib/use.ts:

import { scan } from "../src/scanner2.ts"
export const value: number = scan(1)
export const control: number = "positive control"

The control line is a positive control: it must always report an error.

  1. aft_inspect with scope: ["lib/use.ts"]: Cannot find module '../src/scanner2.ts' and the control error. This is correct, because the module is missing.
  2. Create src/scanner2.ts with AFT write:
    export function scan(n: number): number { return n + 1 }
  3. aft_inspect again, immediately and again after 10 s: both times Cannot find module '../src/scanner2.ts' and the control error. Incorrect.

Control: point the import at ../src/scanner3.ts (an AFT edit), then create src/scanner3.ts from a shell instead of AFT. After 8 s, aft_inspect shows only the control error. The import resolves.

I ran each arm in two packages in the same project: one in a directory excluded through .git/info/exclude and one in a directory that git does not ignore. The results were the same in both, so ignore rules are not the cause.

Probable cause (main 666645637)

After an AFT write, lsp_post_write (crates/aft/src/context.rs:15521) sends didOpen/didChange for the written document. It sends workspace/didChangeWatchedFiles only for project configuration files (notify_watched_config_files, context.rs:15345-15362, filtered by is_config_file_path_with_custom). So the server gets no Created event for a new source file. The TypeScript server keeps its cached failed module lookup for the importer, and opening the new file does not clear it.

For a file that another program creates, the project watcher forwards the change (lsp_forward_classified_watcher_file_events), and the import resolves. The watcher does not do this for the AFT-written file in my test. I did not find where that event is dropped.

Suggested change

When an AFT write or patch creates a file (or deletes one), send workspace/didChangeWatchedFiles with Created (or Deleted) to each server whose root contains the path and which registered watchers for it, as for files that the watcher sees. A move is a Deleted plus a Created.

Effect

Agents get false errors on files that import a module they just wrote, plus follow-on implicit-any errors. They can spend time on a type error that does not exist.

Activity

  1. iceteaSA commented on Oct 29, 2026

    @iceteaSA
    ContributorAuthor

    More data, same module and setup (third run, one package):

    After AFT write created src/scanner4.ts, these did not clear the error. I ran aft_inspect 8 s after each step:

    1. touch src/scanner4.ts from a shell.
    2. Replace the file from a shell (cp f f.tmp && mv -f f.tmp f).
    3. AFT edit on the importer (lib/use.ts), after the module exists.

    So the error stays until the TypeScript server restarts. A module that a shell creates before AFT opens it resolves (the control in the issue). Possibly, when AFT has a file open, AFT does not forward later watcher events for that path to the server as watched-file events. I did not confirm this in the code.

  2. added a commit that references this issue on Oct 30, 2026
  3. aft-alfonso commented on Oct 30, 2026

    @aft-alfonso

    Fixed in v0.63.4. When AFT creates, moves or deletes a file, it now tells the language server, so importing a module AFT just wrote no longer shows a stale "Cannot find module" error. Thanks for the clear report.

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