withastro/astro · critical · Error

Unable to render because it contains an undefined…

Error message

Unable to render ${result.pathname} because it contains an undefined Component!
Did you forget to import the component or is it possible there is a typo?

What it means

Thrown from Astro's streaming JSX renderer when a vnode's type is falsy — the component reference being rendered evaluated to undefined. Astro renders JSX from .astro templates and MDX/MD pages by looking up each element's constructor; an undefined one means the name used in markup was never bound to a real component. Typical causes are a typo, a missing import, an import/export shape mismatch, or a circular import that leaves the binding undefined at render time.

Solutions

  1. Open the page named in the error (result.pathname) and find the JSX element whose component is undefined: verify the import exists and the tag matches it exactly
  2. Check the import shape: .astro and most framework components are default exports (import Header from './Header.astro'), not named exports
  3. Verify file-name casing matches the filesystem exactly
  4. If imports look correct, look for a circular import and move the shared code into a third module
  5. Run astro check (or tsc) to catch missing or misspelled exports before rendering

Example fix

// before — Header.astro has a default export
import { Header } from './Header.astro';
<html><body><Header /></body></html>

// after
import Header from './Header.astro';
<html><body><Header /></body></html>
Defensive patterns

Strategy: type-guard

Validate before calling

---
// dynamic component lookup in frontmatter
import { isRenderableComponent } from '../lib/guards';
const Comp = registry[name];
---
{isRenderableComponent(Comp) ? <Comp {...props} /> : <p>Unknown component: {name}</p>}

Type guard

type Renderable = (...args: any[]) => any;
const isRenderableComponent = (c: unknown): c is Renderable =>
	typeof c === 'function' || (typeof c === 'object' && c !== null && 'render' in c);

Prevention

When it happens

Trigger: Rendering <TypoComp /> where the identifier is misspelled or never imported; import { Header } from './Header.astro' when the module only has a default export (or vice versa); an MDX/.md page using a component passed via the components={{...}} prop with a wrong key; a circular import chain (A imports B imports A) leaving the binding undefined on first render; a component looked up from a map that returned undefined.

Common situations: Renaming an export but not all usages; file-name casing that works on macOS/Windows but breaks on Linux CI (./header.astro vs ./Header.astro); components fetched from data maps that can be absent; refactors that accidentally introduce import cycles between .astro frontmatter and compiled islands.

Related errors


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

Appendix: source

Thrown at packages/astro/src/runtime/server/render/streaming.ts:125

	};

	// Render function for a dynamic node into a (buffered) destination.
	const renderDynamic =
		(node: unknown) =>
		(d: RenderDestination): void | Promise<void> => {
			if (isVNode(node)) {
				return renderJSX(result, node).then((out) => renderChild(d, out));
			}
			return renderChild(d, node);
		};

	// Handle an astro:jsx VNode (JSX in .astro files and MDX/.md pages). Emits
	// HTML elements as static, pushes children, and routes components through
	// the dynamic path.
	const handleVNode = (vnode: AstroVNode) => {
		const type = vnode.type as unknown;
		if (!type) {
			throw new Error(
				`Unable to render ${result.pathname} because it contains an undefined Component!\nDid you forget to import the component or is it possible there is a typo?`,
			);
		}

		// Fragment: process its children.
		if ((type as any) === Fragment) {
			stack.push(vnode.props?.children);
			return;
		}

		// Astro component factory (including `server:defer` islands).
		if (isAstroComponentFactory(type)) {
			const props: Record<string, unknown> = {};
			const slots: Record<string, number | any> = {};
			for (const [key, value] of Object.entries(vnode.props ?? {})) {
				if (
					key === 'children' ||
					(value && typeof value === 'object' && (value as any)['$$slot'])

View on GitHub (pinned to e294953aa8)