denoland/deno · error

invalid --output: dylib path has no file name

Error message

invalid --output: dylib path has no file name: {}

What it means

Same DylibParts decomposition: Path::file_name() is None when the path ends in '..' or is exactly '.' — i.e. the --output value denotes a directory-ish path with no final file component, so there is no dylib file name to derive the app name from.

Solutions

  1. Pass the full dylib file path, not a directory: --output ./build/libapp.dylib.
  2. If you want the bundle in a given folder, name the file and let the bundler create the app alongside it.
  3. Check shell scripts for stray trailing '/' or empty variable segments glued onto '..'.

Example fix

# before
deno desktop compile --output ./build   # directory, no file name
# error: invalid --output: dylib path has no file name: ./build

# after
deno desktop compile --output ./build/libapp.dylib
Defensive patterns

Strategy: validation

Validate before calling

// Guard: --output must be a file path (has a final component), not '.'/'..'/a dir
fn is_file_path(p: &std::path::Path) -> bool {
    p.file_name().map(|f| f != "." && f != "..").unwrap_or(false)
}
assert!(is_file_path(std::path::Path::new(&out)));
// shell equivalent: case "$out" in .|..|*/) echo "--output must be a file path"; exit 1;; esac

Prevention

When it happens

Trigger: Passing --output ., --output .., or a path whose last component normalizes away (trailing '..'), so dylib_path.file_name() returns None.

Common situations: A user points --output at a directory instead of a file (mental model 'output folder'); a script appends a slash or '..' due to variable expansion; CI config reused from a flag that expects a directory.

Related errors


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

Appendix: source

Thrown at cli/tools/desktop.rs:3011

/// The pieces of `dylib_path` we feed into the bundlers, with proper
/// error messages instead of `unwrap` panics on degenerate inputs like
/// `--output /` or `--output .`.
struct DylibParts<'a> {
  parent: &'a Path,
  file_name: &'a std::ffi::OsStr,
  app_name: String,
}

fn dylib_parts(dylib_path: &Path) -> Result<DylibParts<'_>, AnyError> {
  let parent = dylib_path.parent().ok_or_else(|| {
    deno_core::anyhow::anyhow!(
      "invalid --output: dylib path has no parent dir: {}",
      dylib_path.display()
    )
  })?;
  let file_name = dylib_path.file_name().ok_or_else(|| {
    deno_core::anyhow::anyhow!(
      "invalid --output: dylib path has no file name: {}",
      dylib_path.display()
    )
  })?;
  let app_name = dylib_path
    .file_stem()
    .ok_or_else(|| {
      deno_core::anyhow::anyhow!(
        "invalid --output: dylib path has no file stem: {}",
        dylib_path.display()
      )
    })?
    .to_string_lossy()
    .into_owned();
  Ok(DylibParts {
    parent,
    file_name,
    app_name,

View on GitHub (pinned to f7822238ca)