microsoft/TypeScript · error · Error

tracing requires having fs\n(original error: ${e.message ||

Error message

tracing requires having fs\n(original error: ${e.message || e})

What it means

Thrown by `ts.startTracing` when it cannot `require("fs")`. Tracing writes JSON traces to disk and needs the Node `fs` module; if `require("fs")` throws (bundled compiler build, sandboxed/blocked require, non-Node host), `startTracing` aborts. The original error is appended to the message.

Source

Thrown at src/compiler/tracing.ts:66

    let legendPath: string | undefined;
    const legend: TraceRecord[] = [];

    // The actual constraint is that JSON.stringify be able to serialize it without throwing.
    interface Args {
        [key: string]: string | number | boolean | null | undefined | Args | readonly (string | number | boolean | null | undefined | Args)[]; // eslint-disable-line no-restricted-syntax
    }

    /** Starts tracing for the given project. */
    export function startTracing(tracingMode: Mode, traceDir: string, configFilePath?: string): void {
        Debug.assert(!tracing, "Tracing already started");

        if (fs === undefined) {
            try {
                fs = require("fs");
            }
            catch (e) {
                throw new Error(`tracing requires having fs\n(original error: ${e.message || e})`);
            }
        }

        mode = tracingMode;
        typeCatalog.length = 0;

        if (legendPath === undefined) {
            legendPath = combinePaths(traceDir, "legend.json");
        }

        // Note that writing will fail later on if it exists and is not a directory
        if (!fs.existsSync(traceDir)) {
            fs.mkdirSync(traceDir, { recursive: true });
        }

        const countPart = mode === "build" ? `.${process.pid}-${++traceCount}`
            : mode === "server" ? `.${process.pid}`
            : ``;

View on GitHub (pinned to b465fdbfe1)

Solutions

  1. Do not enable tracing in environments without `fs` (gate it behind a runtime check).
  2. Provide an `fs` shim or externalize `fs` as a bundler externals entry.
  3. Run tracing in a plain Node process instead of a bundled one.
  4. If you control the call site, check `typeof require !== "undefined"` and that `require("fs")` succeeds before calling `startTracing`.

Example fix

// before
ts.startTracing(ts.Mode.All, traceDir, configPath); // throws in a bundle w/o fs
// after
try { require("fs"); ts.startTracing(ts.Mode.All, traceDir, configPath); }
catch { /* tracing unavailable in this host; skip */ }
Defensive patterns

Strategy: validation

Validate before calling

let fsAvailable = false;
try { require("fs"); fsAvailable = true; } catch {}
// only call startTracing when fsAvailable is true

Type guard

function canTrace(): boolean { try { require("fs"); return true; } catch { return false; } }

Prevention

When it happens

Trigger: Calling `ts.startTracing(mode, traceDir, configPath)` (directly, or via `--traceResolution`/`--generateTrace` style flows that reach it) in an environment where `fs` is unavailable: a webpack/esbuild bundle of the compiler, a sandbox that blocks built-ins, or a custom host without Node's loader.

Common situations: Bundling the TS compiler for browser/electron use and then enabling tracing; running the compiler under a custom loader that intercepts `require`; CI sandboxes that restrict built-in modules.

Related errors


AI-assisted analysis of microsoft/TypeScript@b465fdbfe1 (2026-08-12). Data as JSON: /api/errors/25df417ddc8ff9f2. Report an issue: GitHub.