{"record":{"id":"7ae7d33f1b146624","repo":"microsoft/TypeScript","slug":"expected-at-least-one-js-file-to-be-emitted-or-at","errorCode":null,"errorMessage":"Expected at least one js file to be emitted or at least one error to be created.","messagePattern":"Expected at least one js file to be emitted or at least one error to be created\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/harness/harnessIO.ts","lineNumber":921,"sourceCode":"        const anyUnfoundSources = ts.contains(sourceTDs, /*value*/ undefined);\r\n        if (anyUnfoundSources) return \"\";\r\n\r\n        const hash = \"#base64,\" + ts.map([outputJSFile.text, sourcemap].concat(sourceTDs.map(td => td!.text)), s => ts.convertToBase64(decodeURIComponent(encodeURIComponent(s)))).join(\",\");\r\n        return \"\\n//// https://sokra.github.io/source-map-visualization\" + hash + \"\\n\";\r\n    }\r\n\r\n    export function doJsEmitBaseline(\r\n        baselinePath: string,\r\n        header: string,\r\n        options: ts.CompilerOptions,\r\n        result: CompileFilesResult,\r\n        tsConfigFiles: readonly TestFile[],\r\n        toBeCompiled: readonly TestFile[],\r\n        otherFiles: readonly TestFile[],\r\n        harnessSettings: TestCaseParser.CompilerSettings,\r\n    ): void {\r\n        if (!options.noEmit && !options.emitDeclarationOnly && result.js.size === 0 && result.diagnostics.length === 0) {\r\n            throw new Error(\"Expected at least one js file to be emitted or at least one error to be created.\");\r\n        }\r\n\r\n        // check js output\r\n        let tsCode = \"\";\r\n        const tsSources = otherFiles.concat(toBeCompiled);\r\n        tsCode += \"//// [\" + header + \"] ////\\r\\n\\r\\n\";\r\n\r\n        for (let i = 0; i < tsSources.length; i++) {\r\n            tsCode += \"//// [\" + ts.getBaseFileName(tsSources[i].unitName) + \"]\\r\\n\";\r\n            tsCode += tsSources[i].content + (i < (tsSources.length - 1) ? \"\\r\\n\" : \"\");\r\n        }\r\n\r\n        let jsCode = \"\";\r\n        result.js.forEach(file => {\r\n            if (jsCode.length && jsCode.charCodeAt(jsCode.length - 1) !== ts.CharacterCodes.lineFeed) {\r\n                jsCode += \"\\r\\n\";\r\n            }\r\n            if (!result.diagnostics.length && !ts.endsWith(file.file, ts.Extension.Json)) {\r","sourceCodeStart":903,"sourceCodeEnd":939,"githubUrl":"https://github.com/microsoft/TypeScript/blob/b465fdbfe175304d9b977da137b2c178ae1091d3/src/harness/harnessIO.ts#L903-L939","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","Confirm the test's input files are actually in `toBeCompiled` (not only `otherFiles`) so the compiler emits for them.","If the test is meant to produce only .d.ts output, route it through the declaration baseline path instead of doJsEmitBaseline.","Inspect `result.diagnostics` and `result.js` in a debugger to see why both are empty for an emit-on configuration."],"exampleFix":"// before — test header omits emit flags, doJsEmitBaseline throws\n// @module: commonjs\n// @Filename: a.ts\nexport const x = 1;\n\n// after — declare that no JS emit is expected\n// @noEmit\n// @module: commonjs\n// @Filename: a.ts\nexport const x = 1;","handlingStrategy":"validation","validationCode":"// Before invoking doJsEmitBaseline, assert the test will do real work.\nfunction shouldRunJsBaseline(options: ts.CompilerOptions, result: CompileFilesResult): boolean {\n  if (options.noEmit || options.emitDeclarationOnly) return true; // harness skips these\n  return result.js.size > 0 || result.diagnostics.length > 0;\n}\nif (!shouldRunJsBaseline(test.options, test.result)) {\n  throw new Error(\"Test mis-configured: enable @noEmit or @emitDeclarationOnly, or ensure inputs produce JS/diagnostics.\");\n}","typeGuard":"function isEmitProducingResult(result: CompileFilesResult): boolean {\n  return result.js.size > 0 || result.diagnostics.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Always set @noEmit or @emitDeclarationOnly explicitly in test metadata when the test does not emit JS.","Keep toBeCompiled non-empty for emit tests; route declaration-only tests through the declaration baseline path.","Add a pre-flight assertion in test setup that result.js or result.diagnostics is non-empty for emit-on tests."],"tags":["test-harness","baseline","emit","compiler-options"],"backgroundTag":null,"analyzedSha":"b465fdbfe175304d9b977da137b2c178ae1091d3","analyzedAt":"2026-08-12T05:38:42.698Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}