microsoft/TypeScript · error · Error

Expected at least one js file to be emitted or at least one

Error message

Expected at least one js file to be emitted or at least one error to be created.

What it means

Thrown by doJsEmitBaseline in the TypeScript test harness when a compiler-output baseline test produces neither emitted JS nor any diagnostics. The guard at harnessIO.ts:921 fires only when options.noEmit and options.emitDeclarationOnly are both false yet result.js.size === 0 and result.diagnostics.length === 0, i.e. the test asserts the compiler did some real work and it did nothing observable.

Source

Thrown at src/harness/harnessIO.ts:921

        const anyUnfoundSources = ts.contains(sourceTDs, /*value*/ undefined);
        if (anyUnfoundSources) return "";

        const hash = "#base64," + ts.map([outputJSFile.text, sourcemap].concat(sourceTDs.map(td => td!.text)), s => ts.convertToBase64(decodeURIComponent(encodeURIComponent(s)))).join(",");
        return "\n//// https://sokra.github.io/source-map-visualization" + hash + "\n";
    }

    export function doJsEmitBaseline(
        baselinePath: string,
        header: string,
        options: ts.CompilerOptions,
        result: CompileFilesResult,
        tsConfigFiles: readonly TestFile[],
        toBeCompiled: readonly TestFile[],
        otherFiles: readonly TestFile[],
        harnessSettings: TestCaseParser.CompilerSettings,
    ): void {
        if (!options.noEmit && !options.emitDeclarationOnly && result.js.size === 0 && result.diagnostics.length === 0) {
            throw new Error("Expected at least one js file to be emitted or at least one error to be created.");
        }

        // check js output
        let tsCode = "";
        const tsSources = otherFiles.concat(toBeCompiled);
        tsCode += "//// [" + header + "] ////\r\n\r\n";

        for (let i = 0; i < tsSources.length; i++) {
            tsCode += "//// [" + ts.getBaseFileName(tsSources[i].unitName) + "]\r\n";
            tsCode += tsSources[i].content + (i < (tsSources.length - 1) ? "\r\n" : "");
        }

        let jsCode = "";
        result.js.forEach(file => {
            if (jsCode.length && jsCode.charCodeAt(jsCode.length - 1) !== ts.CharacterCodes.lineFeed) {
                jsCode += "\r\n";
            }
            if (!result.diagnostics.length && !ts.endsWith(file.file, ts.Extension.Json)) {

View on GitHub (pinned to b465fdbfe1)

Solutions

  1. Add `// @noEmit` or `// @emitDeclarationOnly` to the test file's metadata header if the test is intentionally not producing JS — the guard explicitly skips those cases.
  2. Confirm the test's input files are actually in `toBeCompiled` (not only `otherFiles`) so the compiler emits for them.
  3. If the test is meant to produce only .d.ts output, route it through the declaration baseline path instead of doJsEmitBaseline.
  4. Inspect `result.diagnostics` and `result.js` in a debugger to see why both are empty for an emit-on configuration.

Example fix

// before — test header omits emit flags, doJsEmitBaseline throws
// @module: commonjs
// @Filename: a.ts
export const x = 1;

// after — declare that no JS emit is expected
// @noEmit
// @module: commonjs
// @Filename: a.ts
export const x = 1;
Defensive patterns

Strategy: validation

Validate before calling

// Before invoking doJsEmitBaseline, assert the test will do real work.
function shouldRunJsBaseline(options: ts.CompilerOptions, result: CompileFilesResult): boolean {
  if (options.noEmit || options.emitDeclarationOnly) return true; // harness skips these
  return result.js.size > 0 || result.diagnostics.length > 0;
}
if (!shouldRunJsBaseline(test.options, test.result)) {
  throw new Error("Test mis-configured: enable @noEmit or @emitDeclarationOnly, or ensure inputs produce JS/diagnostics.");
}

Type guard

function isEmitProducingResult(result: CompileFilesResult): boolean {
  return result.js.size > 0 || result.diagnostics.length > 0;
}

Prevention

When it happens

Trigger: Calling doJsEmitBaseline(...) for a test whose CompilerOptions resolve to emit-on, but the CompileFilesResult contains an empty `js` map and zero diagnostics. This happens when a test file is authored for declaration-only or no-emit but its header metadata does not set @noEmit / @emitDeclarationOnly, or when the only output is a source map / d.ts and `result.js` stays empty.

Common situations: A test author copies a declaration-emit test and forgets the `// @emitDeclarationOnly` directive; renaming/refactoring a test so the inputs no longer produce JS; a regression that silently swallows emit; using `// @noEmit` on a test whose harness path still routes through doJsEmitBaseline.

Related errors


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