denoland/deno · error
{} and {} would both be added as "{}". Provide an explicit a
Error message
{} and {} would both be added as "{}". Provide an explicit alias for one of them (ex. `{}`). What it means
With `--unscoped`, `deno add` strips scopes from names so `@a/cli` and `@b/cli` both become the import alias `cli`. Before inserting, it checks for an existing req with the same alias and bails, showing both package names and a concrete aliased command, because otherwise the second add would silently overwrite the first in deno.json.
Source
Thrown at cli/tools/pm/mod.rs:633
bail!("{hint}");
}
let req = AddRmPackageReq::parse(
entry_text,
add_flags.default_registry.map(|r| r.into()),
)
.with_context(|| format!("Failed to parse package: {}", entry_text))?;
match req {
Ok(mut add_req) => {
if add_flags.unscoped {
add_req.use_unscoped_alias();
// packages from different scopes can share an unscoped name
// (ex. `@luca/flag` and `@other/flag`), which would otherwise
// silently overwrite each other in the config
if let Some(existing) =
package_reqs.iter().find(|r| r.alias == add_req.alias)
{
bail!(
"{} and {} would both be added as \"{}\". Provide an explicit alias for one of them (ex. `{}`).",
existing.package_name(),
add_req.package_name(),
add_req.alias,
crate::colors::yellow(format!(
"deno {cmd_name} my-alias@{}",
add_req.package_name()
)),
);
}
}
package_reqs.push(add_req)
}
// Currently unreachable: default_registry is always Some (defaults to Npm),
// so parse() always resolves a prefix. Kept as a safety fallback in case
// the API is called with None from elsewhere.
Err(package_req) => {
if jsr_resolverView on GitHub (pinned to 9ad36f7a2c)
Solutions
- Alias one of them explicitly: `deno add my-cli@npm:@b/cli` (pattern shown in the error message).
- Drop `--unscoped` so each keeps its scoped key `@a/cli`.
- Split into two invocations if both are needed unscoped, aliasing at least one.
Example fix
# before deno add --unscoped @a/cli @b/cli # after deno add --unscoped @a/cli my-cli@npm:@b/cli
Defensive patterns
Strategy: validation
Validate before calling
const specs = process.argv.slice(2); // after --unscoped
const unscoped = (s: string) => s.replace(/^@[^/]+\//, "").split("@")[0];
const seen = new Map<string, string>();
for (const s of specs) {
const alias = unscoped(s);
if (seen.has(alias)) {
console.error(`${seen.get(alias)} and ${s} collide on unscoped alias "${alias}"; alias one explicitly`);
process.exit(1);
}
seen.set(alias, s);
} Prevention
- With --unscoped, alias same-basename packages: `deno add my-cli@npm:@b/cli`.
- Avoid --unscoped when installing several packages sharing a base name.
- Review the generated deno.json imports after every add.
When it happens
Trigger: `deno add --unscoped @a/cli @b/cli` (two packages whose names after the scope are identical), or a second `--unscoped` add colliding with an existing dependency in the same invocation's list.
Common situations: Installing multiple scoped CLIs or libs with the same base name (e.g. @std/cli and @foo/cli); scripts that loop `deno add --unscoped` over package lists.
Related errors
- Failed to install "{}" specifier. If you are trying to insta
- Unexpected package json dependency string: "{string_value}"
- {hint}
- {entry_text} is missing a prefix. Did you mean `{}`?
- Task not found: {}
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/69d77f62538c2f0a.
Report an issue: GitHub.