shadcn-ui/ui · critical · Error

Invalid dependency "${dep}": dependency names cannot start w

Error message

Invalid dependency "${dep}": dependency names cannot start with "-".

What it means

Thrown by assertSafeDependencies when any dependency string, after trim(), starts with "-". Registry-supplied deps are passed straight into the package manager's argument list, so a leading "-" would be parsed as a flag (argument injection). This guard rejects such specifiers before they reach execa; the "--" separator added at call sites is the secondary defense.

Source

Thrown at packages/shadcn/src/utils/updaters/update-dependencies.ts:211

    // https://docs.expo.dev/more/expo-cli/#install
    return "expo"
  }

  return getPackageManager(config.resolvedPaths.cwd)
}

/**
 * Registry-supplied dependency strings are forwarded directly into the package
 * manager's argument list. A specifier beginning with "-" would be interpreted
 * as a flag rather than a package name, letting a malicious registry alter the
 * install source/behavior (argument injection). Reject those before they reach
 * `execa`; the `--` end-of-options separator added at each call site is the
 * second layer of defense.
 */
export function assertSafeDependencies(deps: string[]) {
  for (const dep of deps) {
    if (dep.trim().startsWith("-")) {
      throw new Error(
        `Invalid dependency "${dep}": dependency names cannot start with "-".`
      )
    }
  }
}

async function installWithPackageManager(
  packageManager: Awaited<
    ReturnType<typeof getUpdateDependenciesPackageManager>
  >,
  dependencies: string[],
  devDependencies: string[],
  cwd: string,
  flag?: string
) {
  if (packageManager === "npm") {
    return installWithNpm(dependencies, devDependencies, cwd, flag)
  }

View on GitHub (pinned to efac598707)

Solutions

  1. Edit the registry item and remove the leading "-" from the offending dependency string.
  2. Move install flags (like -D) out of dependencies/devDependencies; use devDependencies for dev deps instead.
  3. If the registry is third-party, do not install it; report the suspicious dependency.
  4. Re-run the add command after the registry is corrected.

Example fix

// registry item (before)
{ "dependencies": ["--registry=https://evil.example.com"] }
// after
{ "dependencies": ["clsx", "tailwind-merge"] }
Defensive patterns

Strategy: validation

Validate before calling

function assertSafeDependencies(deps: string[]) {
  for (const dep of deps) {
    if (dep.trim().startsWith("-")) {
      throw new Error(`unsafe dependency: ${dep}`)
    }
  }
}
assertSafeDependencies(item.dependencies ?? [])
assertSafeDependencies(item.devDependencies ?? [])

Type guard

const areSafeDependencies = (deps: string[]) =>
  deps.every((d) => !d.trim().startsWith("-"))

Try / catch

try {
  await updateDependencies(tree, config)
} catch (e) {
  if (e instanceof Error && /dependency names cannot start/.test(e.message)) {
    // strip the offending dep and report the registry as untrusted
  }
  throw e
}

Prevention

When it happens

Trigger: installWithPackageManager calls assertSafeDependencies(dependencies) and assertSafeDependencies(devDependencies) for pnpm/yarn/bun-style managers; any dep like "--registry=evil" or "-D" from a registry item's dependencies/devDependencies triggers it.

Common situations: A malicious or malformed registry item lists a flag-like string in dependencies; a registry author accidentally includes an install flag (e.g. "-D") inside the deps array; copy-paste of a full install command into the deps field.

Related errors


AI-assisted analysis of shadcn-ui/ui@efac598707 (2026-08-12). Data as JSON: /api/errors/c7a0ca17162fc01a. Report an issue: GitHub.