withastro/astro · error · AstroError
Could not render `${node.name}`. No matching import has been
Error message
Could not render `${node.name}`. No matching import has been found for `${node.name}`. What it means
In MDX, hydration directives like `client:load` require the compiler to pair the JSX element with a concrete import so the island's chunk can be built. The rehype-analyze-astro-metadata pass inspects every component element carrying `client:` (or `server:defer`) and looks up `findMatchingImport`; with no import matching the tag name, it throws the core NoMatchingImport AstroError.
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 52e6c34790)
Solutions
- Add an explicit ES import for the component at the top of the .mdx file.
- Make the imported name match the JSX tag exactly (default import name = tag name).
- Remove the `client:` directive if the element is a plain HTML tag, not a component.
- Remember Astro components themselves cannot hydrate — if the import resolves to a .astro file you'll get the separate misuse warning; use a framework component for islands.
Example fix
import Counter from '../components/Counter'; <Counter client:load />
Defensive patterns
Strategy: validation
Validate before calling
// CI check: MDX files using client:* components must import them
import { globSync } from 'glob';
import fs from 'node:fs';
const importRe = /import\s+([A-Za-z_$][\w$]*)\s+from\s+['"][^'"]+['"]/g;
const tagRe = /<([A-Z][\w.]*)[^>]*\sclient:[a-z]+/g;
for (const f of globSync('src/**/*.mdx')) {
const src = fs.readFileSync(f, 'utf8');
const imported = new Set([...src.matchAll(importRe)].map((m) => m[1]));
for (const m of src.matchAll(tagRe)) {
if (!imported.has(m[1])) throw new Error(`${f}: <${m[1]} client:*> used without a matching import`);
}
} Prevention
- Every component used with client: in MDX gets an explicit import in the same file.
- Keep import names identical to JSX tag names to survive the matcher.
- Add the import-lint to CI; eslint-plugin-mdx with react-refresh rules also catches unused/missing pairs.
When it happens
Trigger: Writing `<Counter client:load />` in an .mdx file without a corresponding `import Counter from '../components/Counter'`, or with a mismatched imported name.
Common situations: Copy-pasting Astro examples into MDX where the import line was omitted; assuming globally registered components work in MDX; shadowing/renaming imports so the tag no longer matches the specifier.
Related errors
- Expected a matching import for component `${tagName}`. Did y
- You are attempting to render <${node.name!} ${clientAttribut
- You are attempting to render <${tagName} ${clientAttr} />, b
- You are attempting to render <${displayName} ${prop} />, but
- [MDX] A remark or rehype plugin attempted to inject invalid
AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18).
Data as JSON: /api/errors/936ca4af452b5bf9.
Report an issue: GitHub.