denoland/deno · error

--outdir is required when bundling HTML entrypoints

Error message

--outdir is required when bundling HTML entrypoints

What it means

Bundling an HTML entrypoint emits multiple files per page (rewritten .html, .js, .css, sourcemaps) that must live in a directory; a single destination or stdout cannot represent them. When any resolved entrypoint is HTML (is_html_entrypoint) and bundle_flags.output_dir is None, the CLI rejects the invocation up front (cli/tools/bundle/mod.rs:146-151).

Source

Thrown at cli/tools/bundle/mod.rs:148

      init_cwd,
      npm_resolver,
      node_resolver,
    );
    plugin_handler.prepare_module_load(&roots).await?;
    let graph = plugin_handler.module_graph_container.graph();
    let mut fully_resolved_roots = IndexSet::with_capacity(graph.roots.len());
    for root in &graph.roots {
      fully_resolved_roots.insert(graph.resolve(root).clone());
    }
    *plugin_handler.resolved_roots.write() = Arc::new(fully_resolved_roots);

    Ok(BundlerInput::Entrypoints(
      roots.into_iter().map(|e| ("".into(), e.into())).collect(),
    ))
  } else {
    // require an outdir when any HTML is present
    if bundle_flags.output_dir.is_none() {
      return Err(deno_core::anyhow::anyhow!(
        "--outdir is required when bundling HTML entrypoints",
      ));
    }
    if bundle_flags.output_path.is_some() {
      return Err(deno_core::anyhow::anyhow!(
        "--output is not supported with HTML entrypoints; use --outdir",
      ));
    }

    // Prepare HTML pages and temp entry modules
    let mut html_pages = Vec::new();
    let mut to_cache_urls = Vec::new();
    let mut entries: Vec<(String, String)> = Vec::new();
    let virtual_modules = Arc::new(VirtualModules::new());

    for html_path in &html_paths {
      let entry = html::load_html_entrypoint(
        init_cwd,

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Add --outdir: 'deno bundle --outdir dist index.html'
  2. If you wanted a single JS file, bundle the script the HTML references instead of the HTML page
  3. Update build scripts/ci.yml that construct the deno bundle command to pass --outdir for HTML targets

Example fix

# before
deno bundle index.html
# after
deno bundle --outdir dist index.html
Defensive patterns

Strategy: validation

Validate before calling

#!/usr/bin/env bash
# Refuse to construct an invalid command: HTML entries require --outdir
entry="$1"; shift
case "$entry" in *.html|*.htm) case " $* " in *' --outdir '*) ;; *) echo 'HTML entrypoint needs --outdir <dir>'; exit 2;; esac;; esac
deno bundle "$entry" "$@"

Type guard

function isHtmlEntrypoint(entry: string): boolean {
  return /\.(html|htm)$/i.test(entry);
}

Prevention

When it happens

Trigger: 'deno bundle index.html' or 'deno bundle page.html style.css' without --outdir; scripts paired with an HTML file so the HTML branch is taken; CI scripts migrating from 'deno bundle src/main.ts out.js' to an HTML page and keeping the old shape.

Common situations: First attempt at the HTML bundling feature; mixing HTML and script entrypoints in one command; build pipelines that assume bundle always writes one file.

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/2cc65e0932c9d5f0. Report an issue: GitHub.