Skip to content

Generated empty JS modules exhaust the NTFS 1,024 hard-link limit #527

Description

@jdpt0

Summary

intercom-client@7.0.3 contains hundreds of byte-identical generated empty runtime modules:

  • 591 CommonJS .js files
  • 591 ESM .mjs files

For example, many CommonJS files contain only:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

Package managers using content-addressed hardlinks may link every identical file to the same underlying file.

On Windows/NTFS, a file can have at most 1,024 hardlinks. Installing the project in multiple Git worktrees can therefore exhaust this limit and cause subsequent installations to fail.

Why this particularly affects AI coding workflows

This is becoming more common with AI coding tools because many agents use a separate Git worktree for each concurrent task.

A developer might previously have had only one or two installations of a repository. With AI agents, it is normal to create several short-lived worktrees and install dependencies in each of them. Concurrent agents can therefore consume hundreds of hardlinks very quickly, even though every worktree belongs to the same repository and uses the same dependency version.

In this case, each installation can add hundreds of links to a single content-addressed cache file. Only a small number of AI-agent worktrees is needed to reach the NTFS limit.

Deleting the affected node_modules directories temporarily releases the links, but the problem returns as new worktrees are created.

Environment

  • Windows with NTFS
  • intercom-client@7.0.3
  • Yarn 4.17.1
  • Yarn nodeLinker: pnpm
  • Multiple Git worktrees using the same global Yarn cache

Error

A subsequent worktree installation eventually fails with an error similar to:

YN0001: UNKNOWN: unknown error, link '...'

Inspecting the affected cache file shows that its NTFS hardlink count has reached exactly 1024.

Reproduction

  1. Configure Yarn to use the pnpm linker:

    nodeLinker: pnpm
  2. Add intercom-client@7.0.3 as a dependency.

  3. Install dependencies on Windows/NTFS:

    yarn install
  4. Create additional Git worktrees for the same repository and run yarn install in each one.

  5. Once the shared cache entry reaches 1,024 links, installation fails while linking one of the generated empty Intercom modules.

The issue can also be observed by hashing the installed package's runtime files. There are groups containing 591 identical .js files and 591 identical .mjs files.

Expected behaviour

Installing intercom-client in multiple projects or worktrees should not exhaust the filesystem's hardlink limit.

Suggested fix

Please make each generated empty runtime module's contents unique.

For example, the generator could include the module's relative path or exported type name in a generated comment:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// Generated module: api/resources/contacts/types/example.js

Another option would be to avoid emitting runtime .js and .mjs files for declarations that exist only at the type level.

Adding the relative module path to the generated comment is sufficient to prevent content-addressed package stores from treating all these files as the same object, without changing runtime behaviour.

Workaround validation

We patched the generated comments locally to include each module's relative path. After applying the patch:

  • Installation succeeded in a second worktree while the original worktree remained installed.
  • CommonJS and ESM imports continued to work.
  • The package's maximum group of identical runtime files dropped from 591 to 74.
  • The problematic shared-cache file received no additional hardlinks.
  • Our application build, typecheck and lint checks passed.

This suggests that making the generated stubs content-unique would resolve the issue without affecting the client's API or runtime behaviour.


For full disclosure, this issue was made with significant help from GPT-5.6-Sol. If you feel it's inappropriate, feel free to close.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions