Skip to main content
ContractError is Solar’s structured validation error. It extends Error with machine-readable fields that describe exactly what went wrong and how to fix it — designed for both AI agents doing programmatic self-correction and human developers reading error output.

When ContractErrors are thrown

Solar throws a ContractError in the following situations:
  • A required prop is missing or null/undefined
  • A prop’s value type doesn’t match the declared schema type
  • A prop’s value is not in the declared enum list
  • A slot prop receives a vnode from the wrong component (when accepts is set)
  • registry.register() receives a value that isn’t the result of a defineComponent call

ContractError properties

name
string
Always 'ContractError'. Use this to identify the error type safely across module boundaries without relying on instanceof.
message
string
A human-readable description of the validation failure, formatted as "ComponentName: prop "propName": expected X, got Y".
component
string
The name of the component that threw the error, as declared in defineComponent({ name }).
prop
string | null
The name of the prop that failed validation, or null for errors that are not specific to a single prop (such as registry validation errors).
expected
string
A description of what value or type was expected, for example 'string', 'slot(Button)', or 'one of ["primary", "secondary"]'.
received
string
A description of what was actually received, for example 'number', 'undefined', or 'slot(Icon)'.
fix
string
A plain-language instruction describing exactly what to change to resolve the error. This field is specifically designed to be passed directly to an AI model as corrective context.

toJSON()

Call toJSON() to get a plain object representation of the error. This is ideal for logging, serialization, and feeding structured context back to an AI agent.
err.toJSON()
// →
{
  "error": "ContractError",
  "component": "Button",
  "prop": "label",
  "expected": "string",
  "received": "number",
  "fix": "Pass a string value for \"label\"",
  "message": "Button: prop \"label\": expected string, got number"
}

Catching ContractErrors

try {
  mountComponent(Button, { label: 99, onClick: handler }, container)
} catch (err) {
  if (err.name === 'ContractError') {
    console.error('Validation failed:', err.toJSON())
    // For AI agents: feed err.toJSON() back to the model
    // The 'fix' field tells the model exactly what to change
  }
}

Using ContractError for AI self-correction

Because toJSON() returns a structured object with a fix field, an AI agent can catch a ContractError, serialize it with toJSON(), and inject it directly into the next generation prompt — no regex parsing required. The fix field is a complete, actionable instruction the model can follow verbatim to produce a corrected component call on the next attempt.
ContractError is exported from Solar and available for instanceof checks. Checking by name also works and is more resilient when the error crosses module or bundle boundaries.
import { ContractError } from './solar/index.js'

if (err instanceof ContractError) { /* ... */ }
// or check by name (works across module boundaries):
if (err.name === 'ContractError') { /* ... */ }