rolldown/rolldown · error

Failed to generate d.ts from runtime-extra-dev.js

Error message

Failed to generate d.ts from runtime-extra-dev.js

What it means

packages/rolldown/build.ts generates TypeScript declarations for the experimental runtime by running the TypeScript compiler over runtime-extra-dev.js. If the emit produces no outputText (the transpile/emit returned nothing usable), the script throws this error to fail the build loudly rather than shipping missing or empty d.ts files.

Solutions

  1. Verify runtime-extra-dev.js exists at the expected path and is non-empty
  2. Log the ts.emit/transpile result and diagnostics to find why outputText is empty
  3. Check the TypeScript version and the compilerOptions used for the emit (target/module must be emit-compatible)
  4. Re-run the build after fixing; if caused by an upstream change, update generateRuntimeEntry to the new TS API

Example fix

// before
const result = ts.transpileModule(src, { compilerOptions });
if (result.outputText) { /* write */ } else { throw new Error('Failed to generate d.ts from runtime-extra-dev.js'); }
// after: surface diagnostics
const result = ts.transpileModule(src, { compilerOptions, reportDiagnostics: true });
if (result.diagnostics?.length) console.error(result.diagnostics);
if (!result.outputText) throw new Error(`Failed to generate d.ts from runtime-extra-dev.js: ${file} (${src.length} bytes)`);
Defensive patterns

Strategy: try-catch

Validate before calling

// before generating, check input exists and is non-empty
if (!fs.existsSync(runtimeExtraDev) || fs.statSync(runtimeExtraDev).size === 0) {
  throw new Error(`runtime-extra-dev.js missing or empty at ${runtimeExtraDev}`);
}

Try / catch

try {
  generateRuntimeEntry();
} catch (e) {
  if (String(e).includes('Failed to generate d.ts')) {
    console.error('TS emit produced no output; check runtime source and TS version');
    process.exit(1);
  }
  throw e;
}

Prevention

When it happens

Trigger: generateRuntimeEntry calls the TypeScript API on runtime-extra-dev.js and the result's outputText is falsy (emit skipped, wrong input file, or ts configuration mismatch), so the else branch throws.

Common situations: Upgrading TypeScript changes emit behavior; the runtime source file is renamed/moved so the compiled input is empty or wrong; tsconfig options (declaration/emit settings) incompatible with the inline transpile call.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of rolldown/rolldown@91b44b9d7b (2026-09-07). Data as JSON: /api/errors/c428d76f4a2bf9bd. Report an issue: GitHub.

Appendix: source

Thrown at packages/rolldown/build.ts:291

  );

  const result = ts.transpileDeclaration(commonRuntimeSource, {
    compilerOptions: {
      ...getTsconfigCompilerOptionsForFile(commonRuntimeInputFile),
      noEmit: false,
      emitDeclarationOnly: true,
    },
    fileName: commonRuntimeInputFile,
  });

  if (result && result.outputText) {
    fs.writeFileSync(outputFile, result.outputText, 'utf-8');
    fs.copyFileSync(
      outputFile,
      nodePath.resolve(buildMeta.buildOutputDir, 'experimental-runtime-types.d.ts'),
    );
  } else {
    throw new Error('Failed to generate d.ts from runtime-extra-dev.js');
  }
}

function readDevRuntimeSources() {
  return {
    commonRuntimeSource: fs.readFileSync(commonRuntimeInputFile, 'utf-8'),
    defaultRuntimeSource: fs.readFileSync(defaultRuntimeInputFile, 'utf-8'),
  };
}

function readDefaultDevRuntimeSource() {
  const { commonRuntimeSource, defaultRuntimeSource } = readDevRuntimeSources();
  return `${commonRuntimeSource}\n${defaultRuntimeSource}`;
}

function getTsconfigCompilerOptionsForFile(file: string) {
  const tsconfigPath = ts.findConfigFile(file, (path) => ts.sys.fileExists(path));
  let compilerOptions = ts.getDefaultCompilerOptions();

View on GitHub (pinned to 91b44b9d7b)