denoland/deno · error · AnyError

'{}' did not have a bin property with a string or non-empty

Error message

'{}' did not have a bin property with a string or non-empty object value

What it means

When Deno resolves a package binary (running an `npm:` specifier as a command), `resolve_bin_entry_value` loads the package.json `bin` field into a map. If that map is empty — bin absent, an empty object, or otherwise unusable — it bails: the package declares no executable, so there is nothing for Deno to run.

Source

Thrown at libs/node_resolver/resolution.rs:2657

  // Search for...
  // > "$basedir/../next/dist/bin/next" "$@"
  // ...which is what it will look like on Windows
  SCRIPT_PATH_RE
    .captures(text)
    .and_then(|c| c.get(1))
    .map(|relative_path| {
      file_path.parent().unwrap().join(relative_path.as_str())
    })
}

fn resolve_bin_entry_value<'a>(
  package_json: &PackageJson,
  bins: &'a BTreeMap<String, BinValue>,
  bin_name: Option<&str>,
) -> Result<&'a BinValue, AnyError> {
  if bins.is_empty() {
    bail!(
      "'{}' did not have a bin property with a string or non-empty object value",
      package_json.path.display()
    );
  }
  let default_bin = package_json.resolve_default_bin_name().ok();
  let searching_bin = bin_name.or(default_bin);
  match searching_bin.and_then(|bin_name| bins.get(bin_name)) {
    Some(bin) => Ok(bin),
    _ => {
      if bins.len() > 1
        && let Some(first) = bins.values().next()
        && bins.values().all(|bin| bin == first)
      {
        return Ok(first);
      }
      if bin_name.is_none()
        && bins.len() == 1
        && let Some(first) = bins.values().next()

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Check whether the package ships a CLI at all: `npm view <pkg> bin` — empty output means it is a library.
  2. If it is a library, import it from code instead: `import lib from 'npm:<pkg>'` in a script, then `deno run script.ts`.
  3. Run a specific exported file directly if the package exposes one: `deno run -A npm:<pkg>/<entry>.js`.
  4. If you own the package, add a `"bin"` field mapping a name to an executable script.

Example fix

# before
$ deno run -A npm:chalk
# error: '...node_modules/chalk/package.json' did not have a bin property with a string or non-empty object value

# after: chalk is a library — import it instead
# main.ts:  import chalk from 'npm:chalk@5';  console.log(chalk.green('ok'));
deno run -A main.ts
Defensive patterns

Strategy: validation

Validate before calling

# confirm the package ships a bin before running it
npm view <pkg> bin   # empty/undefined => `deno run -A npm:<pkg>` will fail

Type guard

type PkgWithBin = { bin: string | Record<string, string> };
function hasUsableBin(p: { bin?: unknown }): p is PkgWithBin {
  if (typeof p.bin === "string") return p.bin.length > 0;
  return typeof p.bin === "object" && p.bin !== null && Object.keys(p.bin).length > 0;
}

Try / catch

const cmd = new Deno.Command(Deno.execPath(), { args: ["run", "-A", `npm:${pkg}`] });
const { stderr, success } = await cmd.output();
if (!success && new TextDecoder().decode(stderr).includes("did not have a bin property")) {
  console.error(`${pkg} is a library (no bin) — import it from code instead of running it`);
}

Prevention

When it happens

Trigger: `deno run -A npm:<pkg>` (or resolving a bin out of a dependency) where the package's package.json has no `bin` field or `"bin": {}`. Typical with pure libraries invoked as if they were CLIs (e.g. `deno run -A npm:chalk`).

Common situations: Confusing an npm library with a CLI package; a package whose bin was removed in a newer major; monorepo packages that hoist their bin into a different sub-package; misspelled package names that resolve to a library.

Related errors


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