denoland/deno · error

invalid {kind} {name:?}: must match [A-Za-z0-9 ._-]+, but co

Error message

invalid {kind} {name:?}: must match [A-Za-z0-9 ._-]+, but contains {c:?}

What it means

The second validate_launcher_name check: names are restricted to ASCII alphanumerics plus space, '.', '_', '-'. Anything else — even inside double quotes — is dangerous because '$', backticks, and '\' expand in POSIX shell and '%' / '^' expand in cmd.exe, so the generated launcher script could execute injected content. The error names the first offending character.

Source

Thrown at cli/tools/desktop.rs:2987

}

/// Reject any name we'd interpolate into a generated launcher script
/// (POSIX shell on macOS/Linux, `.bat` on Windows). Even the
/// double-quoted positions take expansions: `$`, backticks, `\` in
/// bash; `%` and `^` in cmd.exe. The launcher kind context (`kind`)
/// is included in the error to make the failure easy to act on.
fn validate_launcher_name(name: &str, kind: &str) -> Result<(), AnyError> {
  if name.is_empty() {
    bail!("invalid {kind}: name is empty");
  }
  // ASCII-only, alphanumerics + a small whitelist of harmless
  // punctuation. Spaces are allowed because real macOS .app bundles
  // commonly have spaces in their executable names.
  let bad = name.chars().find(|c| {
    !(c.is_ascii_alphanumeric() || matches!(c, ' ' | '.' | '_' | '-'))
  });
  if let Some(c) = bad {
    bail!(
      "invalid {kind} {name:?}: must match [A-Za-z0-9 ._-]+, but contains {c:?}",
    );
  }
  Ok(())
}

/// 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!(

View on GitHub (pinned to f7822238ca)

Solutions

  1. Rewrite the name using only [A-Za-z0-9 ._-] — replace punctuation with '-', '_' or spaces.
  2. Transliterate accented characters (Café -> Cafe) or drop them.
  3. Use the plain name for the launcher/app bundle and keep the fancy spelling for in-app UI text.

Example fix

// before
"desktop": { "name": "Café (démo)" }

// after
"desktop": { "name": "Cafe Demo" }
Defensive patterns

Strategy: type-guard

Validate before calling

const LAUNCHER_NAME_RE = /^[A-Za-z0-9 ._-]+$/;
export function checkAppName(name: string): void {
  if (!LAUNCHER_NAME_RE.test(name)) {
    const bad = [...name].find((c) => !LAUNCHER_NAME_RE.test(c));
    throw new Error(`app name contains disallowed character: ${JSON.stringify(bad)}`);
  }
}

Type guard

function isSafeLauncherName(name: string): boolean {
  return /^[A-Za-z0-9 ._-]+$/.test(name);
}

Prevention

When it happens

Trigger: An app name containing quotes, parentheses, '%', '$', backticks, slashes, or any non-ASCII character (accents, emoji, CJK). Examples that fail: "My App (beta)", "Café", "100% Cool", "A&B".

Common situations: Product/marketing names pasted straight into config; localized names with diacritics; names borrowed from an existing brand that uses punctuation.

Related errors


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