{"record":{"id":"3d4577338c254732","repo":"withastro/astro","slug":"integration-integrationname-is-injecting-a-type","errorCode":null,"errorMessage":"Integration ${integrationName} is injecting a type that does not end with \".d.ts\"","messagePattern":"Integration (.+?) is injecting a type that does not end with \"\\.d\\.ts\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/astro/src/integrations/hooks.ts","lineNumber":161,"sourceCode":"\t\t * @param appId - The id of the app that was toggled\n\t\t * @param callback - The callback to run when the app is toggled\n\t\t */\n\t\tonAppToggled: (appId: string, callback: (data: { state: boolean }) => void) => {\n\t\t\tserver.hot.on(`${serverEventPrefix}:${appId}:toggled`, callback);\n\t\t},\n\t};\n}\n\n// Will match any invalid characters (will be converted to _). We only allow a-zA-Z0-9.-_\nconst SAFE_CHARS_RE = /[^\\w.-]/g;\n\nexport function normalizeCodegenDir(integrationName: string): string {\n\treturn `./integrations/${integrationName.replace(SAFE_CHARS_RE, '_')}/`;\n}\n\nexport function normalizeInjectedTypeFilename(filename: string, integrationName: string): string {\n\tif (!filename.endsWith('.d.ts')) {\n\t\tthrow new Error(\n\t\t\t`Integration ${colors.bold(integrationName)} is injecting a type that does not end with \"${colors.bold('.d.ts')}\"`,\n\t\t);\n\t}\n\treturn `${normalizeCodegenDir(integrationName)}${filename.replace(SAFE_CHARS_RE, '_')}`;\n}\n\ninterface RunHookConfigSetup {\n\tsettings: AstroSettings;\n\tcommand: 'dev' | 'build' | 'preview' | 'sync';\n\tlogger: AstroLogger;\n\tisRestart?: boolean;\n\tfs?: typeof fsMod;\n}\n\nexport async function runHookConfigSetup({\n\tsettings,\n\tcommand,\n\tlogger,","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/withastro/astro/blob/d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca/packages/astro/src/integrations/hooks.ts#L143-L179","documentation":"`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).","triggerScenarios":"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`.","commonSituations":"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.","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."],"exampleFix":"// before\nupdateConfig({ types: [{ filename: 'types.ts', content: decl, declaration: true }] })\n\n// after\nupdateConfig({ types: [{ filename: 'types.d.ts', content: decl, declaration: true }] })","handlingStrategy":"validation","validationCode":"function assertDtsFilename(filename) {\n  if (!filename.endsWith('.d.ts')) {\n    throw new Error(`Type filename must end with .d.ts: ${filename}`);\n  }\n}","typeGuard":"function isDtsFilename(filename) {\n  return typeof filename === 'string' && filename.endsWith('.d.ts');\n}","tryCatchPattern":"null","preventionTips":["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."],"tags":["integrations","typescript","config","types"],"backgroundTag":null,"analyzedSha":"d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca","analyzedAt":"2026-08-12T13:37:29.035Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}