{"record":{"id":"53cd5d5faefcbdc4","repo":"withastro/astro","slug":"expected-a-matching-import-for-component-tagnam","errorCode":null,"errorMessage":"Expected a matching import for component `${tagName}`. Did you forget to import it?","messagePattern":"Expected a matching import for component `(.+?)`\\. Did you forget to import it\\?","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/integrations/mdx/src/satteri/hast-astro-metadata.ts","lineNumber":104,"sourceCode":"\t}\n}\n\nfunction processJsxNode(\n\tnode: MdxJsxHastNode,\n\tctx: HastVisitorContext,\n\timports: Map<string, Set<ImportSpecifier>>,\n\tfilePath: string,\n) {\n\tconst tagName = node.name;\n\tif (!tagName || !isComponent(tagName)) return;\n\n\tconst hasClient = hasDirective(node, 'client:');\n\tconst hasServerDefer = !hasClient && hasDirective(node, 'server:defer');\n\tif (!hasClient && !hasServerDefer) return;\n\n\tconst matchedImport = findMatchingImport(tagName, imports);\n\tif (!matchedImport) {\n\t\tthrow new Error(\n\t\t\t`Expected a matching import for component \\`${tagName}\\`. Did you forget to import it?`,\n\t\t);\n\t}\n\n\tif (matchedImport.path.endsWith('.astro') && hasClient) {\n\t\tlet clientAttr = 'client:*';\n\t\tfor (const a of node.attributes) {\n\t\t\tif (a.type === 'mdxJsxAttribute' && a.name.startsWith('client:')) {\n\t\t\t\tclientAttr = a.name;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tconsole.warn(\n\t\t\t`You are attempting to render <${tagName} ${clientAttr} />, but ${tagName} 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.`,\n\t\t);\n\t}\n\n\tconst resolvedPath = resolvePath(matchedImport.path, filePath);","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/withastro/astro/blob/d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca/packages/integrations/mdx/src/satteri/hast-astro-metadata.ts#L86-L122","documentation":"In the Sätteri (MDX) metadata analyzer, `analyzeAstroMetadata` requires every JSX component carrying a `client:` or `server:defer` directive to have a statically-visible matching import. When `findMatchingImport(tagName, imports)` returns falsy, it throws a plain `Error` with a 'Did you forget to import it?' hint. This mirrors `NoMatchingImport` but is the Sätteri code path's local equivalent.","triggerScenarios":"Same family as error 268 but in the Sätteri pipeline: `<Comp client:visible />` (or `server:defer`) in MDX with no matching static import. Tag name doesn't match the imported binding. Component provided via provider/MDX provider component map rather than an import.","commonSituations":"Using the Sätteri MDX processor and referencing a component by a hydration directive without importing it. Renaming imports. Components supplied through `components={{}}` prop instead of imports (these are not statically importable).","solutions":["Add a top-level `import` for the component used with `client:`/`server:defer`.","Match the imported name to the JSX tag exactly.","If the component is provided via the MDX `components` prop (not an import), remove the `client:` directive — it cannot be statically analyzed as an island.","Switch to a static re-export the analyzer can follow."],"exampleFix":"import { Chart } from '../components/Chart.tsx';\n\n<Chart client:visible />","handlingStrategy":"validation","validationCode":"function assertIslandImports(tree: any, imports: Map<string, Set<any>>) {\n  const missing: string[] = [];\n  visit(tree, (n: any) => {\n    if (!n.name || !/^[A-Z]/.test(n.name)) return;\n    const hasClient = n.attributes?.some((a: any) => a.name?.startsWith('client:'));\n    const hasDefer = n.attributes?.some((a: any) => a.name === 'server:defer');\n    if ((hasClient || hasDefer) && !imports.has(n.name)) missing.push(n.name);\n  });\n  return missing;\n}","typeGuard":"function isStaticallyImported(tagName: string, imports: Map<string, Set<unknown>>): boolean {\n  return imports.has(tagName);\n}","tryCatchPattern":null,"preventionTips":["Import every component used with `client:`/`server:defer`.","Don't rely on the MDX `components` prop for islands.","Lint Sätteri MDX files for hydration directives without imports."],"tags":["mdx","satteri","hydration","imports","build"],"backgroundTag":null,"analyzedSha":"d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca","analyzedAt":"2026-08-12T13:37:29.035Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}