preactjs/preact · error · Error
Component's "ref" property should be a function, or an objec
Error message
Component's "ref" property should be a function, or an object created by createRef(), but got [${typeof vnode.ref}] instead
${serializeVNode(vnode)}
${getOwnerStack(vnode)} What it means
Thrown from options._diff when vnode.ref is defined but is neither a function, an object (the shape returned by createRef()/useRef()), nor a string ref permitted via preact-compat's $$typeof marker. Refs must be a callback or a ref object so Preact can attach the DOM node; any other primitive (number, boolean, string without compat) is rejected.
Source
Thrown at debug/src/debug.js:178
` 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)}`
);
}
if (typeof vnode.type == 'string') {
for (const key in vnode.props) {
if (
key[0] === 'o' &&
key[1] === 'n' &&
typeof vnode.props[key] != 'function' &&
vnode.props[key] != null
) {
throw new Error(
`Component's "${key}" property should be a function, ` +
`but got [${typeof vnode.props[key]}] instead\n` +View on GitHub (pinned to e881e7e838)
Solutions
- Replace string refs with createRef or callback refs: `const r = useRef(null); <input ref={r}/>`.
- If you must use string refs, ensure 'preact/compat' is aliased so the $$typeof marker is present.
- Audit ref assignments — `typeof ref` must be 'function' or 'object'.
- For forwarded refs, use forwardRef from 'preact/compat' rather than passing a raw prop named ref.
Example fix
// before (legacy string ref)
class Form extends Component {
render() { return <input ref='email' />; }
}
// after
import { createRef } from 'preact';
class Form extends Component {
email = createRef();
render() { return <input ref={this.email} />; }
} Defensive patterns
Strategy: type-guard
Validate before calling
function isValidRef(ref) {
if (ref == null) return true;
if (typeof ref === 'function') return true;
if (typeof ref === 'object' && 'current' in ref) return true; // createRef/useRef shape
return false;
}
// before assigning
if (!isValidRef(maybeRef)) throw new Error('ref must be function or { current } object'); Type guard
/** @param {unknown} r */
function isPreactRef(r) {
if (r == null) return false;
return typeof r === 'function' || (typeof r === 'object' && 'current' in r);
} Prevention
- Use createRef()/useRef() exclusively — never string refs unless preact/compat is aliased.
- Type ref props as `Ref<T> | undefined` in TS so non-conforming values are caught at compile time.
- When forwarding refs through HOCs use forwardRef from 'preact/compat'.
When it happens
Trigger: Passing a string ref without preact-compat installed: `<input ref='inputRef'/>`; passing a number or boolean: `ref={0}` or `ref={true}`; assigning ref to the result of an expression that yields a primitive; forwarding a ref prop that was unexpectedly a primitive.
Common situations: Copy-paste from a React class component using string refs (legacy); ref forwarding through a prop typed loosely as any; HOC that clones a child but passes through a mutated ref; version mismatch where preact-compat is no longer present (Preact 10+ ships refs as functions/objects only).
Related errors
- Undefined parent passed to render(), this is the second argu
- Expected a valid HTML node as a second argument to render. R
- Undefined component passed to createElement() You likely fo
- Invalid type passed to createElement(): ${type} Did you acc
- Invalid type passed to createElement(): ${Array.isArray(type
AI-assisted analysis of preactjs/preact@e881e7e838 (2026-08-13).
Data as JSON: /api/errors/473071903868c854.
Report an issue: GitHub.