withastro/astro · error · Error
Integration ${colors.bold(integrationName)} is injecting a t
Error message
Integration ${colors.bold(integrationName)} is injecting a type that does not end with "${colors.bold('.d.ts')}" What it means
Integrations can inject TypeScript declaration files via `injectType({ filename })`. Astro normalizes each injected filename into the codegen directory, but requires it to be a declaration file: normalizeInjectedTypeFilename() throws this plain Error when the filename does not end with `.d.ts`. It is a contract violation by the integration, surfaced at config setup time.
Source
Thrown at packages/astro/src/integrations/hooks.ts:161
* @param appId - The id of the app that was toggled
* @param callback - The callback to run when the app is toggled
*/
onAppToggled: (appId: string, callback: (data: { state: boolean }) => void) => {
server.hot.on(`${serverEventPrefix}:${appId}:toggled`, callback);
},
};
}
// Will match any invalid characters (will be converted to _). We only allow a-zA-Z0-9.-_
const SAFE_CHARS_RE = /[^\w.-]/g;
export function normalizeCodegenDir(integrationName: string): string {
return `./integrations/${integrationName.replace(SAFE_CHARS_RE, '_')}/`;
}
export function normalizeInjectedTypeFilename(filename: string, integrationName: string): string {
if (!filename.endsWith('.d.ts')) {
throw new Error(
`Integration ${colors.bold(integrationName)} is injecting a type that does not end with "${colors.bold('.d.ts')}"`,
);
}
return `${normalizeCodegenDir(integrationName)}${filename.replace(SAFE_CHARS_RE, '_')}`;
}
interface RunHookConfigSetup {
settings: AstroSettings;
command: 'dev' | 'build' | 'preview' | 'sync';
logger: AstroLogger;
isRestart?: boolean;
fs?: typeof fsMod;
}
export async function runHookConfigSetup({
settings,
command,
logger,View on GitHub (pinned to 52e6c34790)
Solutions
- Pass a filename ending in `.d.ts`: injectType({ filename: 'my-integration.d.ts' }).
- If the name is dynamic, append the extension after sanitizing: `${name}.d.ts`.
- If the error comes from a third-party integration, update it or file an issue - the call site is in the integration, not your app.
Example fix
// before - inside an integration's astro:config:setup
updateConfig({ injectType: { filename: 'my-types.ts' } });
// after
updateConfig({ injectType: { filename: 'my-types.d.ts' } }); Defensive patterns
Strategy: validation
Validate before calling
// inside an integration, before injectType
function injectedTypeFilename(name: string): string {
const filename = name.endsWith('.d.ts') ? name : name + '.d.ts';
if (!filename.endsWith('.d.ts')) throw new Error('type filename must end with .d.ts');
return filename;
} Prevention
- Always append '.d.ts' when constructing injected type filenames dynamically.
- Cover injectType calls with a unit test that runs the setup hook against a stub config.
- Type hook parameters with the exported HookParameters types so contract drift is visible.
When it happens
Trigger: An integration's `astro:config:setup` hook calling injectType({ filename: 'types.ts' }) or 'index.d'; filenames built dynamically (e.g. name + '.d') that lose the extension; porting an integration from an older API that accepted arbitrary filenames.
Common situations: Authoring or maintaining a community integration; a typo in the extension; code generating the filename from a variable that already contains an extension.
Related errors
- Integration ${colors.bold(integration.name)} has an unnamed
- Renderer ${colors.bold(renderer.name)} does not provide a se
- The "${integration.name}" integration is trying to add the "
- The "${integration.name}" integration is trying to add middl
- Integration "${maybeConflictingIntegration}" conflicts with
AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18).
Data as JSON: /api/errors/e1175389732c83e6.
Report an issue: GitHub.