preactjs/preact · critical · Error

Undefined component passed to createElement() You likely fo

Error message

Undefined component passed to createElement()

You likely forgot to export your component or might have mixed up default and named imports${serializeVNode(vnode)}

${getOwnerStack(vnode)}

What it means

Thrown from options._diff when a vnode's type is strictly undefined. In Preact the vnode type is the component function/class or tag string; undefined means createElement received nothing usable as the first argument. The message points at a missing export or a default/named import mismatch, and it appends the serialized vnode and the owner component stack for diagnosis.

Source

Thrown at debug/src/debug.js:148

		}

		if (!isValid) {
			let componentName = getDisplayName(vnode);
			throw new Error(
				`Expected a valid HTML node as a second argument to render.	Received ${parentNode} instead: render(<${componentName} />, ${parentNode});`
			);
		}

		if (oldRoot) oldRoot(vnode, parentNode);
	};

	options._diff = vnode => {
		let { type } = vnode;

		hooksAllowed = true;

		if (type === undefined) {
			throw new Error(
				'Undefined component passed to createElement()\n\n' +
					'You likely forgot to export your component or might have mixed up default and named imports' +
					serializeVNode(vnode) +
					`\n\n${getOwnerStack(vnode)}`
			);
		} else if (type != null && typeof type == 'object') {
			if (type._children !== undefined && type._dom !== undefined) {
				throw new Error(
					`Invalid type passed to createElement(): ${type}\n\n` +
						'Did you accidentally pass a JSX literal as JSX twice?\n\n' +
						`  let My${getDisplayName(vnode)} = ${serializeVNode(type)};\n` +
						`  let vnode = <My${getDisplayName(vnode)} />;\n\n` +
						'This usually happens when you export a JSX literal and not the component.' +
						`\n\n${getOwnerStack(vnode)}`
				);
			}

			throw new Error(

View on GitHub (pinned to e881e7e838)

Solutions

  1. Check the source module: confirm the component is exported with the matching syntax — `export default function Foo` vs `export function Foo`.
  2. Adjust the import to match: use `import Foo from` for default, `import { Foo } from` for named, or `import Foo, { Bar } from` for both.
  3. For ESM/CJS interop use `import pkg from './mod'; const Foo = pkg.default || pkg`.
  4. Eliminate circular imports — log the imported value at module top to confirm it is defined before render.

Example fix

// before — Foo.js has `export default function Foo()`
import { Foo } from './Foo'; // Foo is undefined
render(<Foo />, root);

// after
import Foo from './Foo';
render(<Foo />, root);
Defensive patterns

Strategy: type-guard

Validate before calling

function assertComponent(component, name) {
  if (component === undefined || component === null) {
    throw new Error(`Component "${name}" is ${String(component)}. Check the export/import style.`);
  }
  if (typeof component !== 'function') {
    throw new Error(`Expected a component function/class for "${name}", got ${typeof component}.`);
  }
  return component;
}

import * as Mod from './Foo';
const Foo = assertComponent(Mod.default ?? Mod.Foo, 'Foo');
render(<Foo />, root);

Type guard

/** @param {unknown} c */
function isPreactComponentType(c) {
  return typeof c === 'function' || typeof c === 'string';
}

Prevention

When it happens

Trigger: Named import where the module uses default export: import { Foo } from './Foo' when Foo is exported default; default import where the module uses a named export: import Foo from './Foo' when Foo is a named export; circular import that evaluates to undefined at first use; barrel file (index.js) re-exporting a component that has not yet been defined; dynamic import used synchronously before resolution.

Common situations: Interop between ESM and CommonJS where default becomes { default: Component }; tree-shaking misconfiguration stripping a used export; HMR stale module where the replaced module lost the export; conditional export that resolves to undefined in the current environment; forgetting to add `export` to a function component declaration.

Related errors


AI-assisted analysis of preactjs/preact@e881e7e838 (2026-08-13). Data as JSON: /api/errors/91e2129f27228e98. Report an issue: GitHub.