withastro/astro · error · AstroError
NoMatchingImport
NoMatchingImport
Error message
Could not render `${componentName}`. No matching import has been found for `${componentName}`. What it means
`rehype-analyze-astro-metadata` scans MDX for JSX elements that are components with a `client:` (or `server:defer`) directive — i.e. island candidates. It then matches the tag name against imports parsed from the file. If `findMatchingImport(tagName, imports)` returns nothing, it throws `AstroError` with `NoMatchingImport` so the user gets a clear, attributed build error.
Source
Thrown at packages/integrations/mdx/src/rehype-analyze-astro-metadata.ts:49
const imports = parseImports(tree.children);
visit(tree, (node) => {
if (node.type !== 'mdxJsxFlowElement' && node.type !== 'mdxJsxTextElement') return;
const tagName = node.name;
if (
!tagName ||
!isComponent(tagName) ||
!(hasClientDirective(node) || hasServerDeferDirective(node))
)
return;
// From this point onwards, `node` is confirmed to be an island component
// Match this component with its import source
const matchedImport = findMatchingImport(tagName, imports);
if (!matchedImport) {
throw new AstroError(
AstroErrorData.NoMatchingImport.message(node.name!),
AstroErrorData.NoMatchingImport.hint,
);
}
// If this is an Astro component, that means the `client:` directive is misused as it doesn't
// work on Astro components as it's server-side only. Warn the user about this.
if (matchedImport.path.endsWith('.astro')) {
const clientAttribute = node.attributes.find(
(attr) => attr.type === 'mdxJsxAttribute' && attr.name.startsWith('client:'),
) as MdxJsxAttribute | undefined;
if (clientAttribute) {
console.warn(
`You are attempting to render <${node.name!} ${
clientAttribute.name
} />, but ${node.name!} is an Astro component. Astro components do not render in the client and should not have a hydration directive. Please use a framework component for client rendering.`,
);
}View on GitHub (pinned to d081033d5f)
Solutions
- Add a static ESM `import` for the component used with `client:*` at the top of the `.mdx` file.
- Verify the imported binding name exactly matches the JSX tag name.
- If using a member expression, assign it to a capitalized local const and import that.
- Remove the `client:` directive if the component is not meant to hydrate.
Example fix
import Counter from '../components/Counter.astro'; <Counter client:load />
Defensive patterns
Strategy: validation
Validate before calling
function componentsWithClientDirectiveHaveImports(tree: any, imports: Map<string, Set<any>>) {
const missing: string[] = [];
visit(tree, (n: any) => {
if (n.type !== 'mdxJsxFlowElement' && n.type !== 'mdxJsxTextElement') return;
if (!n.name || !/^[A-Z]/.test(n.name)) return;
const hasClient = n.attributes?.some((a: any) => a.type === 'mdxJsxAttribute' && a.name.startsWith('client:'));
if (hasClient && !imports.has(n.name)) missing.push(n.name);
});
return missing;
} Type guard
function isImportedComponent(name: string, imports: Map<string, Set<unknown>>): boolean {
return imports.has(name);
} Prevention
- Always import components used with `client:*` directives.
- Match import binding names to JSX tag names exactly.
- Lint MDX for client directives without imports.
When it happens
Trigger: Using `<MyComp client:load />` in MDX without a corresponding `import MyComp from '...'`. Typo in the tag name vs the import. Component used via JSX member expression (`<UI.Button />`) that the importer cannot match. Import is dynamic/conditional and not statically visible.
Common situations: Forgot to import a component used with a hydration directive. Renamed an import but not the JSX usage. Mixing default vs named imports incorrectly. Component comes from a re-export the static parser doesn't follow.
Related errors
- Expected a matching import for component `${tagName}`. Did y
- [MDX] A remark or rehype plugin attempted to inject invalid
- [MDX] A Sätteri plugin attempted to inject invalid frontmatt
- The markdown processor "${processor.name}" does not provide
- [RSS] You can only glob entries within 'src/pages/' when pas
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/538aa941e788a74e.
Report an issue: GitHub.