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

  1. Rename event-handler props so they start with 'on' (e.g. `handleClick` → `onClick`)
  2. Move non-event function props to a capitalized function component that consumes them instead of passing them to intrinsic elements
  3. 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

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


AI-assisted analysis of honojs/hono@e2740d5a1b (2026-08-28). Data as JSON: /api/errors/84fff1971b1224d4. Report an issue: GitHub.