denoland/deno · critical

expected file "{file}" to exist

Error message

expected file "{file}" to exist

What it means

Deno's CLI build script zstd-compresses checked-in JS sources (cli/tsc/99_main_compiler.js, 97_ts_host.js, 98_lsp.js, 00_typescript.js, and the tsc/dts .d.ts set) for release builds. compress_source (cli/build.rs:219-249) canonicalizes each listed path and panics 'expected file ... to exist' when canonicalize fails, i.e. the file is registered for compression but missing from the checkout. Compression only runs when !cfg!(debug_assertions) (build.rs:190), so debug builds pass while release builds and cargo publish verification fail.

Source

Thrown at cli/build.rs:223

    let relative_str = relative.to_string_lossy().replace('\\', "/");
    generated.push_str(&format!(
      "      maybe_compressed_static_asset!(\"{}\", false),\n",
      relative_str
    ));
  }

  generated.push_str("    ]\n");
  generated.push_str("  };\n");
  generated.push_str("}\n");

  std::fs::write(out_dir.join("node_types.rs"), generated).unwrap();
}

fn compress_source(out_dir: &Path, file: &str) {
  #[allow(clippy::disallowed_methods, reason = "build code")]
  let path = Path::new(file)
    .canonicalize()
    .unwrap_or_else(|_| panic!("expected file \"{file}\" to exist"));
  let contents = std::fs::read(&path).unwrap();

  println!("cargo:rerun-if-changed={}", path.display());

  let compressed = zstd::bulk::compress(&contents, 19).unwrap();
  let mut out = out_dir.join(file.trim_start_matches("../"));
  let mut ext = out
    .extension()
    .map(|s| s.to_string_lossy())
    .unwrap_or_default()
    .into_owned();
  ext.push_str(".zstd");
  out.set_extension(ext);
  std::fs::create_dir_all(out.parent().unwrap()).unwrap();
  let mut file = std::fs::OpenOptions::new()
    .create(true)
    .truncate(true)
    .write(true)

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Restore the exact path from the panic text: git status --short cli/tsc, then git checkout -- cli/tsc (or rerun the step that generates the tsc bundle).
  2. Clear the build-script output cache so the file list is recomputed: cargo clean -p deno or remove target/**/build/deno-*/.
  3. Verify the file exists (ls cli/tsc/<file>) before rebuilding; if it is genuinely untracked, regenerate or re-checkout rather than touching build.rs.

Example fix

# before
cargo build --release
# panic: expected file "../tsc/00_typescript.js" to exist

# after
git checkout -- cli/tsc
cargo build --release
Defensive patterns

Strategy: validation

Validate before calling

# preflight before a release build
for f in cli/tsc/00_typescript.js cli/tsc/97_ts_host.js \
         cli/tsc/98_lsp.js cli/tsc/99_main_compiler.js; do
  test -f "$f" || { echo "missing $f — run: git checkout -- cli/tsc"; exit 1; }
done
compgen -G 'cli/tsc/dts/*.d.ts' > /dev/null || { echo 'missing dts files'; exit 1; }

Prevention

When it happens

Trigger: cargo build --release or cargo publish with one of cli/tsc/*.js or a tsc/dts/*.d.ts absent; partial or shallow clones; stale OUT_DIR file lists after files were added/renamed; a file removed by tooling or a bad .gitignore rule.

Common situations: Fresh machines where the generated/checked-out tsc assets are incomplete; branch switches that change the .d.ts set while the build cache keeps an old manifest; case-insensitive filesystems mis-checking-out differing capitalizations.

Related errors


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