withastro/astro · error · Error

The "${integration.name}" integration is trying to add the "

Error message

The "${integration.name}" integration is trying to add the "${name}" client directive, but it already exists.

What it means

`addClientDirective` rejects a directive whose `name` is already present in either `settings.clientDirectives` (built-in or previously built) or `addedClientDirectives` (already added this config-setup pass). Client directive names must be globally unique.

Source

Thrown at packages/astro/src/integrations/hooks.ts:275

					injectRoute: (injectRoute) => {
						if (injectRoute.entrypoint == null && 'entryPoint' in injectRoute) {
							logger.warn(
								null,
								`The injected route "${injectRoute.pattern}" by ${integration.name} specifies the entry point with the "entryPoint" property. This property is deprecated, please use "entrypoint" instead.`,
							);
							injectRoute.entrypoint = injectRoute.entryPoint as string;
						}
						updatedSettings.injectedRoutes.push({ ...injectRoute, origin: 'external' });
					},
					addWatchFile: (path) => {
						updatedSettings.watchFiles.push(path instanceof URL ? fileURLToPath(path) : path);
					},
					addDevToolbarApp: (entrypoint) => {
						updatedSettings.devToolbarApps.push(entrypoint);
					},
					addClientDirective: ({ name, entrypoint }) => {
						if (updatedSettings.clientDirectives.has(name) || addedClientDirectives.has(name)) {
							throw new Error(
								`The "${integration.name}" integration is trying to add the "${name}" client directive, but it already exists.`,
							);
						}
						// TODO: this should be performed after astro:config:done
						addedClientDirectives.set(
							name,
							buildClientDirectiveEntrypoint(name, entrypoint, settings.config.root),
						);
					},
					addMiddleware: ({ order, entrypoint }) => {
						if (typeof updatedSettings.middlewares[order] === 'undefined') {
							throw new Error(
								`The "${integration.name}" integration is trying to add middleware but did not specify an order.`,
							);
						}
						logger.debug(
							'middleware',
							`The integration ${integration.name} has added middleware that runs ${

View on GitHub (pinned to d081033d5f)

Solutions

  1. Rename your custom directive to a unique name not used by built-ins or other loaded integrations.
  2. Remove one of the conflicting integrations, or check whether the directive is already provided.
  3. Guard registration by checking existing directive names before calling `addClientDirective`.

Example fix

// before — two integrations both register 'foo'
addClientDirective({ name: 'foo', entrypoint: '...' })

// after — namespace the directive name per integration
addClientDirective({ name: '@mine/foo', entrypoint: '...' })
Defensive patterns

Strategy: validation

Validate before calling

const BUILTIN = new Set(['load','idle','visible','media','only']);
function isDirectiveNameTaken(name, settings, added) {
  return settings.clientDirectives.has(name) || added.has(name) || BUILTIN.has(name);
}

Type guard

function isUniqueDirectiveName(name, settings, added) {
  return !settings.clientDirectives.has(name) && !added.has(name);
}

Try / catch

null

Prevention

When it happens

Trigger: Two integrations both call `addClientDirective({ name: 'foo', ... })`, or an integration registers a name that collides with Astro's built-in directives (`client:load`, `client:idle`, `client:visible`, `client:media`, `client:only`).

Common situations: Installing two integrations that define the same custom client directive; re-registering a directive on config restart; naming a custom directive identically to a built-in.

Related errors


AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12). Data as JSON: /api/errors/6442d6146da1bf9a. Report an issue: GitHub.