message property — ContractErrors also expose component, prop, expected, received, and fix.
ContractError
ContractErrors are thrown when a prop contract is violated or the registry/mount API is misused. They serialize cleanly to JSON, which makes them useful for AI agents — catch them, call.toJSON(), and include the result in the agent’s context.
Required prop missing
Message:ComponentName: prop "propName": expected a value (required), got undefined
Cause: A prop marked required: true was not passed.
Fix: Pass a value for the prop. Check registry.manifest() or the component’s defineComponent call to see which props are required.
Wrong prop type
Message:ComponentName: prop "propName": expected string, got number
Cause: A prop was passed with the wrong JavaScript type.
Fix: Pass the type declared in the component’s schema. Use registry.manifest() to see the expected type for each prop.
Invalid enum value
Message:ComponentName: prop "variant": expected one of ["primary", "secondary"], got "danger"
Cause: A string prop with an enum constraint received a value not in the allowed set.
Fix: Use one of the values listed in the error. Enum options are also visible in registry.manifest() output.
Wrong slot type
Message:ComponentName: prop "icon": expected a vnode (slot), got string
Cause: A prop typed slot received a plain value instead of a rendered component vnode.
Fix: Pass the output of h() or a component render call, not a raw string or number.
Wrong slot source
Message:ComponentName: prop "icon": expected slot(Icon), got slot(Badge)
Cause: A slot prop has an accepts constraint — only vnodes produced by a specific component are allowed — and the wrong component was passed.
Fix: Pass a vnode from the required component.
Array expected
Message:ComponentName: prop "items": expected array, got string
Cause: A prop typed array received a non-array value.
Fix: Wrap the value in an array, or verify the data source is producing an array.
registry.register() — not a component
Message:Unknown: expected a component created with defineComponent(), got function
Cause: A plain function was passed to registry.register() instead of a defineComponent result.
Fix: Wrap the function with defineComponent before registering.
mountComponent() — not a component
Message:Unknown: expected a component created with defineComponent(), got plain function
Cause: A plain function was passed to mountComponent().
Fix: Use the result of defineComponent(), not a raw function.
mountComponent() — not registered
Message:Button: expected component to be registered via registry.register(), got unregistered component
Cause: mountComponent was called before the component was added to the registry.
Fix: Call registry.register(Button) before mountComponent(Button, ...).
defineComponent errors
These are thrown during component definition, before any rendering occurs.Missing name
Message:defineComponent: "name" is required
Cause: The name field was omitted from the defineComponent call.
Fix: Add a name string. Names must be unique across the registry.
Missing render
Message:defineComponent(Button): "render" is required
Cause: The render function was omitted.
Fix: Add a render function that returns a vnode.
Hook context errors
Hooks must be called during a component’s render function. Calling them outside render throws a plainError.
| Hook | Error message |
|---|---|
useState | useState called outside of a component render |
useMemo | useMemo called outside of a component render |
useResource | useResource called outside of a component render |
useSubscription | useSubscription called outside of a component render |
onMount | onMount called outside of a component render |
onUnmount | onUnmount called outside of a component render |
useRoute | useRoute called outside of a component render |
render.
Fix: Move the hook call into the render function body.
Console warnings
These do not throw — they are development-time warnings logged to the console.Unknown prop
Message:Button: unknown prop "colour" passed but not declared in schema
Cause: A prop was passed that doesn’t appear in the component’s props schema.
Fix: Either remove the extra prop, or add it to the component’s schema if it should be supported. This commonly surfaces as a typo (colour instead of color).