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
- Rename your custom directive to a unique name not used by built-ins or other loaded integrations.
- Remove one of the conflicting integrations, or check whether the directive is already provided.
- 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
- Namespace custom directive names per integration.
- Avoid the built-in client:* names.
- Check existing directives before registering.
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
- Integration ${integrationName} is injecting a type that does
- Integration ${integration.name} has an unnamed renderer.
- Renderer ${renderer.name} does not provide a serverEntrypoin
- The "${integration.name}" integration is trying to add middl
- The adapter ${adapter.name} doesn't provide a feature map. I
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/6442d6146da1bf9a.
Report an issue: GitHub.