denoland/deno · error

native tsc exited with

Error message

native tsc exited with {} without parseable diagnostics{}

What it means

The native tsc child process exited non-zero but its output contained no diagnostics Deno could parse. That means tsc itself failed — internal error, malformed generated tsconfig, bad option plumbing — rather than finding type errors. Deno appends whatever tsc printed (stdout, else stderr) as the detail.

Solutions

  1. Read the appended detail — it usually names the exact bad option or shows the crash
  2. Remove or simplify `compilerOptions` in deno.json until the check runs, then re-add options one by one
  3. Update deno; if the detail is empty or shows a pure tsc crash, report with a minimal repro

Example fix

// before (deno.json): misspelled target crashes tsc
{ "compilerOptions": { "target": "esnextt" } }

// after
{ "compilerOptions": { "target": "esnext" } }
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate compilerOptions against known tsc option names before check runs
const config = JSON.parse(await Deno.readTextFile("deno.json"));
const known = new Set(["target", "lib", "strict", "jsx", "paths", "types"]);
for (const key of Object.keys(config.compilerOptions ?? {})) {
  if (!known.has(key)) throw new Error(`unknown compilerOption: ${key}`);
}

Try / catch

Catch the error and surface the appended detail verbatim — it contains tsc's raw output naming the failing option or crash; fix the config rather than retrying.

Prevention

When it happens

Trigger: A tsc crash (stack trace, out of memory), an invalid option forwarded from `compilerOptions` into the generated tsconfig, or a tsc CLI error — anything that exits non-zero without diagnostic-shaped output lines.

Common situations: Invalid or misspelled `compilerOptions` in deno.json being passed through to tsc; exotic `extends` chains; tsc running out of memory on very large projects.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/f97dc2c4036a3abc. Report an issue: GitHub.

Appendix: source

Thrown at cli/tools/check.rs:395

    log::error!("{}\n", diagnostics);
    return Err(deno_core::anyhow::anyhow!("Type checking failed."));
  }

  // tsc exited non-zero but we have nothing to show. If it printed diagnostic
  // lines we deliberately dropped (e.g. `noImplicitOverride` in remote modules),
  // its exit code is expected - treat the check as clean. Only when tsc produced
  // no recognizable diagnostics at all is this a genuine failure (an internal
  // error or a malformed generated config); surface whatever it printed then.
  let tsc_reported_diagnostics =
    crate::tsc::native::output_has_diagnostics(&stdout);
  if !output.status.success() && !tsc_reported_diagnostics {
    let detail = stdout.trim();
    let detail = if detail.is_empty() {
      stderr.trim()
    } else {
      detail
    };
    return Err(deno_core::anyhow::anyhow!(
      "native tsc exited with {} without parseable diagnostics{}",
      output.status,
      if detail.is_empty() {
        String::new()
      } else {
        format!(":\n{detail}")
      }
    ));
  }

  // Type-checked clean: record the hash so an unchanged re-check skips tsc.
  if let Some(check_hash) = maybe_check_hash {
    type_check_cache.add_check_hash(check_hash);
  }

  Ok(())
}

View on GitHub (pinned to 9ad36f7a2c)