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

  1. Pass a filename ending in `.d.ts`: injectType({ filename: 'my-integration.d.ts' }).
  2. If the name is dynamic, append the extension after sanitizing: `${name}.d.ts`.
  3. 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

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


AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18). Data as JSON: /api/errors/e1175389732c83e6. Report an issue: GitHub.