denoland/deno · error

No main module.

Error message

No main module.

What it means

resolve_main_module_with_resolver maps the active subcommand (run, bench, compile, ...) to its entry module. For subcommands that have no main module - eval, repl, task, install, and others - the match falls into a bail with "No main module." instead of returning a specifier.

Source

Thrown at cli/args/mod.rs:899

                resolver,
                default_resolve,
              )?
            }
          }
          DenoSubcommand::Serve(run_flags) => self
            .resolve_main_module_with_resolver_if_bare(
              &run_flags.script,
              resolver,
              || {
                resolve_url_or_path_normalized(
                  &run_flags.script,
                  self.initial_cwd(),
                )
                .map_err(|e| e.into())
              },
            )?,
          _ => {
            bail!("No main module.")
          }
        })
      })
      .as_ref()
      .map_err(|err| deno_core::anyhow::anyhow!("{}", err))
  }

  pub fn resolve_main_module(&self) -> Result<&ModuleSpecifier, AnyError> {
    self.resolve_main_module_with_resolver(None)
  }

  pub fn resolve_file_header_overrides(
    &self,
  ) -> HashMap<ModuleSpecifier, HashMap<String, String>> {
    let maybe_main_specifier = self.resolve_main_module().ok();
    let maybe_content_type = self.flags.ext.as_ref().and_then(|ext| {
      let media_type = MediaType::from_filename(&format!("file.{}", ext));
      media_type.as_content_type()

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Check the active DenoSubcommand variant before asking for a main module
  2. Use the subcommand-specific flags directly (e.g. run_flags.script) for non-run subcommands
  3. Fix the CLI invocation so the intended subcommand is parsed

Example fix

// before
let main = flags.resolve_main_module()?; // deno eval flags -> No main module.

// after
if let DenoSubcommand::Run(_) = &flags.subcommand {
  let main = flags.resolve_main_module()?;
}
Defensive patterns

Strategy: validation

Validate before calling

use deno_args::DenoSubcommand;

fn has_main_module(flags: &Flags) -> bool {
  matches!(
    flags.subcommand,
    DenoSubcommand::Run(_) | DenoSubcommand::Bench(_) | DenoSubcommand::Compile(_)
  )
}

if !has_main_module(&flags) {
  return Err("this subcommand has no main module");
}

Prevention

When it happens

Trigger: Calling flags.resolve_main_module() (directly or through an API that needs the entry specifier) when the parsed CLI flags correspond to a subcommand without a main module, e.g. deno eval or deno repl arguments.

Common situations: Embedders reusing deno CLI argument plumbing; code assuming every invocation has an entry file; subcommand flags parsed differently than expected.

Related errors


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