withastro/astro · error · AstroError

NoMatchingImport

NoMatchingImport

Error message

Could not render `${componentName}`. No matching import has been found for `${componentName}`.

What it means

`generateHydrateScript` builds the `<script type="module">` that hydrates an island. It needs `metadata.componentExport.value` (the resolved export name) to know what to import on the client. When that value is falsy, Astro never recorded a matching import/export for the component and cannot emit a working hydration script, so it throws `NoMatchingImport`.

Source

Thrown at packages/astro/src/runtime/server/hydration.ts:134

interface HydrateScriptOptions {
	renderer: SSRLoadedRenderer;
	result: SSRResult;
	astroId: string;
	props: Record<string | number, any>;
	attrs: Record<string, string> | undefined;
}

/** For hydrated components, generate a <script type="module"> to load the component */
export async function generateHydrateScript(
	scriptOptions: HydrateScriptOptions,
	metadata: Required<AstroComponentMetadata>,
): Promise<SSRElement> {
	const { renderer, result, astroId, props, attrs } = scriptOptions;
	const { hydrate, componentUrl, componentExport } = metadata;

	if (!componentExport.value) {
		throw new AstroError({
			...AstroErrorData.NoMatchingImport,
			message: AstroErrorData.NoMatchingImport.message(metadata.displayName),
		});
	}

	const island: SSRElement = {
		children: '',
		props: {
			// This is for HMR, probably can avoid it in prod
			uid: astroId,
		},
	};

	// Attach renderer-provided attributes
	if (attrs) {
		for (const [key, value] of Object.entries(attrs)) {
			island.props[key] = escapeHTML(value);
		}

View on GitHub (pinned to d081033d5f)

Solutions

  1. Import the component with a static, analyzable import (`import Foo from './Foo'`) so Astro can record its export.
  2. Remove the `client:*` directive if the component doesn't need hydration.
  3. If the component comes from an integration/collection, render it through the documented API that preserves the export reference.
  4. Re-run `astro sync` / rebuild so import metadata is regenerated.

Example fix

// before — dynamic component reference Astro can't trace
const Comp = registry[name];
<Comp client:load />   // NoMatchingImport

// after — static import
import Counter from '../components/Counter.astro';
<Counter client:load />
Defensive patterns

Strategy: validation

Validate before calling

// Tooling-time: confirm a statically analyzable import exists for a hydrated component
import type { Component } from 'astro';
function assertHydratable(Comp: unknown, name: string): void {
  if (Comp == null) {
    throw new Error(`Cannot hydrate '${name}': no resolvable import/export found`);
  }
}

Type guard

const isHydratableComponent = (v: unknown): boolean =>
  typeof v === 'function' || (typeof v === 'object' && v !== null);

Prevention

When it happens

Trigger: A component tagged with a `client:*` directive could not be statically resolved to a named/default export at build time (the import analysis found no usable export); the component reference is a dynamic/computed value Astro can't trace; the renderer's client entry didn't supply an export name.

Common situations: Trying to hydrate a component that is imported through an opaque wrapper, a function call, or a re-export Astro can't analyze; MDX components whose export Astro couldn't resolve; rendering a component from `astro:content` or a collection in a way that loses the export reference; missing/incorrect renderer client entry.

Related errors


AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12). Data as JSON: /api/errors/b4395ac197ec9b5b. Report an issue: GitHub.