preactjs/preact · critical · Error
Invalid type passed to createElement(): ${Array.isArray(type
Error message
Invalid type passed to createElement(): ${Array.isArray(type) ? 'array' : type} What it means
Thrown from options._diff when vnode.type is a non-null object that does NOT carry the _children/_dom markers (so it is not a stray vnode), but is still invalid as a component type — e.g. a plain object, a Map, a Promise, or an array. Arrays are reported literally as 'array' for clarity. This is the catch-all for object types Preact cannot render.
Source
Thrown at debug/src/debug.js:166
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(
'Invalid type passed to createElement(): ' +
(Array.isArray(type) ? 'array' : type)
);
}
if (
vnode.ref !== undefined &&
typeof vnode.ref != 'function' &&
typeof vnode.ref != 'object' &&
!('$$typeof' in vnode) // allow string refs when preact-compat is installed
) {
throw new Error(
`Component's "ref" property should be a function, or an object created ` +
`by createRef(), but got [${typeof vnode.ref}] instead\n` +
serializeVNode(vnode) +
`\n\n${getOwnerStack(vnode)}`
);
}View on GitHub (pinned to e881e7e838)
Solutions
- Inspect vnode.type at runtime: `console.log(typeof type, type)` — it must be a function, class, or string.
- If the component is defined as an object literal, wrap it in a function: `const Comp = () => <obj {...props}/>`.
- For arrays, map children instead: `<>{items.map(i => <Item key={i.id} />)}</>` rather than `<items/>`.
- Check that imports resolve to a function/class — re-export issues can yield object module namespace records.
Example fix
// before
const config = { label: 'Hi' };
render(<config />, root);
// after
function Config() {
return <div>{config.label}</div>;
}
render(<Config />, root); Defensive patterns
Strategy: type-guard
Validate before calling
function assertValidVNodeType(type) {
if (type == null || typeof type === 'object') {
throw new Error(`Invalid vnode type: ${Array.isArray(type) ? 'array' : type}. Expected string|function|class.`);
}
return type;
}
// before constructing a vnode dynamically
assertValidVNodeType(MyType); Type guard
/** @param {unknown} t */
function isValidPreactType(t) {
if (typeof t === 'string' || typeof t === 'function') return true;
// Allow null to skip rendering, disallow other objects
return t === null;
} Prevention
- Always pass a function/class or string tag as the first arg to createElement/h.
- Avoid spreading config objects into the type position.
- Map arrays of data to arrays of elements; never use an array as a type.
When it happens
Trigger: Passing a plain config object as a component: `<{} as any/>`; passing an array of components where one component was expected; passing a Promise (pre-Suspense) or a Map/Set as type; spreading a props object into the type position by mistake.
Common situations: Accidental destructuring swap: `const { type } = config; <type/>` where type is an object; HOC pipeline that returns a descriptor object instead of a component; migrating from a framework whose components are objects (e.g. Vue options objects) without wrapping; type-erased TypeScript where a discriminated union collapses to object.
Related errors
- Undefined component passed to createElement() You likely fo
- Invalid type passed to createElement(): ${type} Did you acc
- Undefined parent passed to render(), this is the second argu
- Expected a valid HTML node as a second argument to render. R
- Component's "ref" property should be a function, or an objec
AI-assisted analysis of preactjs/preact@e881e7e838 (2026-08-13).
Data as JSON: /api/errors/03eb8857e5b572b2.
Report an issue: GitHub.