honojs/hono · error · Error
Invalid prop '${key}' of type 'function' supplied to '${tag}
Error message
Invalid prop '${key}' of type 'function' supplied to '${tag}'. What it means
During hono/jsx server-side serialization, function-valued props are only allowed for event handlers (props starting with 'on') and 'ref'. Any other function prop cannot be rendered into HTML, so Hono throws with the offending prop key and tag.
Source
Thrown at src/jsx/base.ts:261
// Do nothing
} else if (typeof v === 'number' || (v as HtmlEscaped).isEscaped) {
buffer[0] += ` ${key}="${v}"`
} else if (typeof v === 'boolean' && booleanAttributes.includes(key)) {
if (v) {
buffer[0] += ` ${key}=""`
}
} else if (key === 'dangerouslySetInnerHTML') {
if (children.length > 0) {
throw new Error('Can only set one of `children` or `props.dangerouslySetInnerHTML`.')
}
children = [raw(v.__html)]
} else if (v instanceof Promise) {
buffer[0] += ` ${key}="`
buffer.unshift('"', v)
} else if (typeof v === 'function') {
if (!key.startsWith('on') && key !== 'ref') {
throw new Error(`Invalid prop '${key}' of type 'function' supplied to '${tag}'.`)
}
// maybe event handler for client components, just ignore in server components
} else {
buffer[0] += ` ${key}="`
escapeToBuffer(v.toString(), buffer)
buffer[0] += '"'
}
}
if (emptyTags.includes(tag as string) && children.length === 0) {
buffer[0] += '/>'
return
}
buffer[0] += '>'
childrenToStringToBuffer(children, buffer)
View on GitHub (pinned to e2740d5a1b)
Solutions
- Rename event-handler props so they start with 'on' (e.g. `handleClick` → `onClick`)
- Move non-event function props to a capitalized function component that consumes them instead of passing them to intrinsic elements
- For data derived from functions, compute the value before rendering and pass the result as a prop
Example fix
// before
<option formatter={(v) => v.toUpperCase()}>{value}</option>
// after
<option data-value={value.toUpperCase()}>{value.toUpperCase()}</option> Defensive patterns
Strategy: validation
Validate before calling
const safeProps = Object.fromEntries(
Object.entries(props).filter(
([k, v]) => !(typeof v === 'function' && !k.startsWith('on') && k !== 'ref')
)
) Type guard
const isSerializableProp = (key: string, v: unknown): boolean =>
typeof v !== 'function' || key.startsWith('on') || key === 'ref' Try / catch
null
Prevention
- Keep event-handler prop names prefixed with 'on'
- Pass computed values, not functions, to intrinsic elements on the server
- Route function props only to capitalized function components
When it happens
Trigger: Passing a callback like `formatter`, `renderItem`, `getValue`, `onClick`-mismatched names (e.g. `handleClick` not starting with 'on'), or a `ref`-like prop to a plain string tag (HTML element) in server-rendered JSX.
Common situations: Porting React client components to hono/jsx server components and passing render callbacks; passing a function to an intrinsic element where it was previously a client component prop; passing comparator/sorter functions as props on lowercase tags.
Related errors
- Can only set one of `children` or `props.dangerouslySetInner
- style sheet not found
- Event handler for "${key}" is not a function
- Async component is not supported in renderToString
- getServerSnapshot is required for server side rendering
AI-assisted analysis of honojs/hono@e2740d5a1b (2026-08-28).
Data as JSON: /api/errors/84fff1971b1224d4.
Report an issue: GitHub.