withastro/astro · error · Error
${integration} does not appear to be a valid package name!
Error message
${integration} does not appear to be a valid package name! What it means
During `astro add`, each requested integration string is parsed by parseIntegrationName (via parseNpmName). If parsing returns null the spec is not a recognizable npm package spec, and `astro add` throws this Error naming the offending input. This runs after assertValidPackageName, so the spec passed the injection guard but still is not a valid npm name.
Source
Thrown at packages/astro/src/cli/add/index.ts:856
async function validateIntegrations(
integrations: string[],
flags: yargsParser.Arguments,
logger: AstroLogger,
): Promise<IntegrationInfo[]> {
// First, validate all package names to prevent command injection
for (const integration of integrations) {
assertValidPackageName(integration);
}
const spinner = clack.spinner({ withGuide: false });
spinner.start('Resolving packages...');
try {
const integrationEntries = await Promise.all(
integrations.map(async (integration): Promise<IntegrationInfo> => {
const parsed = parseIntegrationName(integration);
if (!parsed) {
throw new Error(`${bold(integration)} does not appear to be a valid package name!`);
}
let { scope, name, tag } = parsed;
let pkgJson;
let pkgType: 'first-party' | 'third-party';
if (scope && scope !== '@astrojs') {
pkgType = 'third-party';
} else {
const firstPartyPkgCheck = await fetchPackageJson('@astrojs', name, tag);
if (firstPartyPkgCheck instanceof Error) {
if (firstPartyPkgCheck.message) {
spinner.message(yellow(firstPartyPkgCheck.message));
}
spinner.message(yellow(`${bold(integration)} is not an official Astro package.`));
if (!(await askToContinue({ flags, logger }))) {
throw new Error(
`No problem! Find our official integrations at ${cyan(
'https://astro.build/integrations',View on GitHub (pinned to d081033d5f)
Solutions
- Use the npm package name only: `astro add @astrojs/tailwind`, `astro add react`.
- For a scoped third-party package, include the full scope: `astro add @myorg/integration`.
- Omit registry URLs, versions prefixed wrongly, and file paths.
- Re-run with the corrected argument; double-check shell escaping of `@` and `/`.
Example fix
# before astro add https://registry.npmjs.org/@astrojs/react astro add @astrojs # after astro add @astrojs/react
Defensive patterns
Strategy: validation
Validate before calling
function isValidNpmSpec(spec: string): boolean {
return /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*(?:@[^@]+)?$/.test(spec);
} Type guard
function isNpmPackageName(v: unknown): v is string {
return typeof v === 'string' && /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(v);
} Prevention
- Pass only the package name to `astro add` (no URL, no path).
- Quote scoped names in your shell to protect @ and /.
- Copy integration names from astro.build/integrations.
When it happens
Trigger: Passing an argument to `astro add` that is not a valid scoped/unscoped npm package spec — e.g. a URL, a path, a name with illegal characters, an empty string, a bare version, or a malformed scoped spec like `@/foo`.
Common situations: Typing `astro add https://example.com/x`; passing `astro add @astrojs`; forgetting the package name within a scope; copy-pasting a registry URL instead of the package name; shell-quoting that drops part of the argument.
Related errors
- ${packageName} doesn't appear to be an integration or an ada
- Unable to fetch ${integration}. Does the package exist?
- Unknown error parsing tsconfig.json or jsconfig.json. Could
- No problem! Find our official integrations at https://astro.
- ${key} expects a "${defaultType}" value!
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/e977e907c34521a8.
Report an issue: GitHub.