microsoft/typescript-go · warning · Error

Found ${unusedBaselines.length} unused baseline file(s). Run

Error message

Found ${unusedBaselines.length} unused baseline file(s). Run 'hereby baseline-accept' to delete them.

What it means

StopTracing serializes the legend (the mapping of per-checker types_*.json files, sorted by TypesPath) with json.MarshalIndent before writing legend.json. This error wraps a marshal failure of []TraceRecord — which for plain string/path fields is essentially unreachable in practice; it exists as a defensive wrap. It would only fire if a TraceRecord ever carried a value the encoder rejects (unsupported type, or a custom Marshaler returning an error).

Source

Thrown at Herebyfile.mjs:765

            const unusedBaselines = await checkUnusedBaselines(trackingDir);
            if (unusedBaselines.length > 0) {
                console.error(pc.red(`\nFound ${unusedBaselines.length} unused baseline file(s):`));
                for (const baseline of unusedBaselines.slice(0, 20)) {
                    console.error(pc.red(`  ${baseline}`));
                }
                if (unusedBaselines.length > 20) {
                    console.error(pc.red(`  ... and ${unusedBaselines.length - 20} more`));
                }

                // Create .delete files for each unused baseline so baseline-accept can remove them
                for (const baseline of unusedBaselines) {
                    const deleteFilePath = path.join(localBaseline, baseline + ".delete");
                    await fs.promises.mkdir(path.dirname(deleteFilePath), { recursive: true });
                    await fs.promises.writeFile(deleteFilePath, "");
                }
                console.error(pc.red(`\nRun 'hereby baseline-accept' to delete them.`));

                throw new Error(`Found ${unusedBaselines.length} unused baseline file(s). Run 'hereby baseline-accept' to delete them.`);
            }
        }
    }
    finally {
        if (cleanupTracking) {
            cleanupTracking();
        }
    }
}

export const test = task({
    name: "test",
    description: "Runs all tests. This is the most typical test task to need.",
    run: runTests,
});

async function runTestBenchmarks() {
    warnIfTypeScriptSubmoduleNotCloned();

View on GitHub (pinned to 1bcfa18d79)

Solutions

  1. If you maintain tsgo and just hit this, inspect the TraceRecord fields you added — one holds a value the encoder can't serialize (func, chan, NaN/Inf float).
  2. Coerce such values to strings or *float64 with NaN omitted before appending to tr.legend.
  3. For library users: report it upstream — with stock TraceRecord this indicates a build mismatch or patched tree.
Defensive patterns

Strategy: try-catch

Try / catch

if err := tr.StopTracing(); err != nil {
	if strings.Contains(err.Error(), "failed to marshal legend file") {
		// marshal-side defect, not I/O: report with tracing config; trace/types files may still be intact
		log.Printf("legend marshal failed (report upstream): %v", err)
	}
}

Prevention

When it happens

Trigger: Calling StopTracing after a legend entry was populated with a field value json.MarshalIndent cannot encode: a NaN/Inf where a number is expected, a func/chan-typed value, or a type implementing json.Marshaler whose MarshalJSON errors. With the current TraceRecord (path strings), no realistic input triggers it; it mostly guards future field additions.

Common situations: Almost never seen in the field. Theoretically after refactors that add richer Args/metadata to TraceRecord; a custom JSON shim rejecting a value type.

Related errors


AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16). Data as JSON: /api/errors/e205a501e6e88ded. Report an issue: GitHub.