withastro/astro · error · Error
Integration ${integrationName} is injecting a type that does
Error message
Integration ${integrationName} is injecting a type that does not end with ".d.ts" What it means
`normalizeInjectedTypeFilename` requires every type file an integration injects via `updateConfig({ types... })` to end in `.d.ts` so Astro can place it correctly under the integration's codegen directory. Filenames not ending in `.d.ts` are rejected with a plain Error (no AstroError code).
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 d081033d5f)
Solutions
- Rename the injected type file so it ends with `.d.ts` (e.g. `'my-types.d.ts'`).
- Confirm the filename passed to the injection API is exactly what you intend — no extra suffix or extension.
- Update the integration to follow the `.d.ts` requirement documented for type injection.
Example fix
// before
updateConfig({ types: [{ filename: 'types.ts', content: decl, declaration: true }] })
// after
updateConfig({ types: [{ filename: 'types.d.ts', content: decl, declaration: true }] }) Defensive patterns
Strategy: validation
Validate before calling
function assertDtsFilename(filename) {
if (!filename.endsWith('.d.ts')) {
throw new Error(`Type filename must end with .d.ts: ${filename}`);
}
} Type guard
function isDtsFilename(filename) {
return typeof filename === 'string' && filename.endsWith('.d.ts');
} Try / catch
null
Prevention
- Always name injected type files with a .d.ts suffix.
- Add a lint asserting injected filenames end in .d.ts.
- Follow the integration type-injection examples in Astro docs.
When it happens
Trigger: An integration's `astro:config:setup` (or equivalent) hook calls the type-injection path with a filename like `'types.ts'`, `'router.d.mts'`, or `'astro-env.d'` — anything whose suffix isn't exactly `.d.ts`.
Common situations: Authoring a custom integration and passing a normal `.ts` filename by mistake; renaming a type file but forgetting the `.d.ts` convention; an integration built against an older API that accepted other extensions.
Related errors
- Integration ${integration.name} has an unnamed renderer.
- Renderer ${renderer.name} does not provide a serverEntrypoin
- The "${integration.name}" integration is trying to add the "
- 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/3d4577338c254732.
Report an issue: GitHub.