Error Codes

Complete reference for all Constela validation and runtime errors

Overview

Constela provides descriptive error codes to help you quickly identify and fix issues in your programs. Each error code follows the format CATEGORY_SPECIFIC.

SCHEMA_INVALID

When it occurs: The program structure does not match the expected schema.

Common causes:

  • Missing required fields (version, state, actions, view)
  • Invalid field types
  • Malformed JSON

How to fix:

json
// Invalid - missing version
{
  "state": { ... },
  "view": { ... }
}

// Valid
{
  "version": "1.0",
  "state": { ... },
  "actions": [],
  "view": { ... }
}

UNDEFINED_STATE

When it occurs: A state expression references a state field that does not exist.

Common causes:

  • Typo in state name
  • Forgot to declare the state field
  • State name mismatch between declaration and usage

How to fix:

json
// Error: UNDEFINED_STATE for "counter"
{
  "state": {
    "count": { "type": "number", "initial": 0 }
  },
  "view": {
    "kind": "text",
    "value": { "expr": "state", "name": "counter" }  // Wrong name!
  }
}

// Fixed: Use correct state name
{
  "value": { "expr": "state", "name": "count" }
}

UNDEFINED_ACTION

When it occurs: An event handler references an action that does not exist.

Common causes:

  • Typo in action name
  • Action not defined in actions array
  • Case sensitivity issues

How to fix:

json
// Error: UNDEFINED_ACTION for "Increment"
{
  "actions": [
    { "name": "increment", "steps": [...] }
  ],
  "view": {
    "kind": "element",
    "tag": "button",
    "props": {
      "onClick": { "event": "click", "action": "Increment" }  // Case mismatch!
    }
  }
}

// Fixed: Match exact action name
{
  "props": {
    "onClick": { "event": "click", "action": "increment" }
  }
}

VAR_UNDEFINED

When it occurs: A variable expression references a variable that is not in scope.

Common causes:

  • Using var expression outside of an each loop or component
  • Typo in variable name
  • Variable name mismatch with as declaration

How to fix:

json
// Error: VAR_UNDEFINED for "item"
{
  "kind": "each",
  "items": { "expr": "state", "name": "items" },
  "as": "todo",  // Declared as "todo"
  "body": {
    "kind": "text",
    "value": { "expr": "var", "name": "item" }  // Wrong name!
  }
}

// Fixed: Use correct variable name
{
  "value": { "expr": "var", "name": "todo" }
}

DUPLICATE_ACTION

When it occurs: Two or more actions share the same name.

Common causes:

  • Copy-paste error
  • Forgot to rename duplicated action

How to fix:

json
// Error: DUPLICATE_ACTION for "handleClick"
{
  "actions": [
    { "name": "handleClick", "steps": [...] },
    { "name": "handleClick", "steps": [...] }  // Duplicate!
  ]
}

// Fixed: Use unique names
{
  "actions": [
    { "name": "handleClickPrimary", "steps": [...] },
    { "name": "handleClickSecondary", "steps": [...] }
  ]
}

UNSUPPORTED_VERSION

When it occurs: The specified DSL version is not supported.

Common causes:

  • Using a version that does not exist
  • Typo in version string

How to fix:

json
// Error: UNSUPPORTED_VERSION for "2.0"
{
  "version": "2.0",
  ...
}

// Fixed: Use supported version
{
  "version": "1.0",
  ...
}

COMPONENT_NOT_FOUND

When it occurs: A component node references a component that is not defined.

Common causes:

  • Component not defined in components object
  • Typo in component name
  • Case sensitivity issues

How to fix:

json
// Error: COMPONENT_NOT_FOUND for "button"
{
  "components": {
    "Button": { ... }
  },
  "view": {
    "kind": "component",
    "name": "button"  // Case mismatch!
  }
}

// Fixed: Match exact component name
{
  "kind": "component",
  "name": "Button"
}

COMPONENT_PROP_MISSING

When it occurs: A required component prop is not provided.

Common causes:

  • Forgot to pass a required prop
  • Typo in prop name

How to fix:

json
// Error: COMPONENT_PROP_MISSING for "label"
{
  "components": {
    "Button": {
      "props": {
        "label": { "type": "string" }  // Required prop
      },
      "view": { ... }
    }
  },
  "view": {
    "kind": "component",
    "name": "Button",
    "props": {}  // Missing label!
  }
}

// Fixed: Provide required prop
{
  "kind": "component",
  "name": "Button",
  "props": {
    "label": { "expr": "lit", "value": "Click me" }
  }
}

COMPONENT_CYCLE

When it occurs: A component directly or indirectly references itself, creating an infinite loop.

Common causes:

  • Component A uses Component B, which uses Component A
  • Component using itself in its own view

How to fix:

json
// Error: COMPONENT_CYCLE detected
{
  "components": {
    "Card": {
      "props": { "title": { "type": "string" } },
      "view": {
        "kind": "component",
        "name": "Card",  // Self-reference!
        "props": { ... }
      }
    }
  }
}

// Fixed: Remove circular reference
{
  "components": {
    "Card": {
      "props": { "title": { "type": "string" } },
      "view": {
        "kind": "element",
        "tag": "div",
        "children": [...]
      }
    }
  }
}

COMPONENT_PROP_TYPE

When it occurs: A prop value does not match the expected type.

Common causes:

  • Passing wrong type (e.g., number instead of string)
  • Expression evaluates to wrong type

How to fix:

json
// Error: COMPONENT_PROP_TYPE for "count" (expected number)
{
  "components": {
    "Counter": {
      "props": {
        "count": { "type": "number" }
      },
      "view": { ... }
    }
  },
  "view": {
    "kind": "component",
    "name": "Counter",
    "props": {
      "count": { "expr": "lit", "value": "42" }  // String, not number!
    }
  }
}

// Fixed: Use correct type
{
  "props": {
    "count": { "expr": "lit", "value": 42 }
  }
}

PARAM_UNDEFINED

When it occurs: A param expression references a parameter that is not available.

Common causes:

  • Using param expression outside of action steps
  • Typo in parameter name
  • Accessing wrong parameter context

How to fix:

json
// Error: PARAM_UNDEFINED for "data"
{
  "do": "set",
  "target": "result",
  "value": { "expr": "param", "name": "data" }  // Wrong param name!
}

// Fixed: Use correct parameter name
// In onSuccess, use "result" for response data
{
  "do": "set",
  "target": "result",
  "value": { "expr": "param", "name": "result" }
}

UNDEFINED_STYLE

When it occurs: A style expression references a style preset that does not exist.

Common causes:

  • Typo in style name
  • Style not defined in styles object
  • Case sensitivity issues

How to fix:

json
// Error: UNDEFINED_STYLE for "buttons"
{
  "styles": {
    "button": { ... }
  },
  "view": {
    "props": {
      "className": { "expr": "style", "name": "buttons" }  // Typo!
    }
  }
}

// Fixed: Use correct style name
{
  "props": {
    "className": { "expr": "style", "name": "button" }
  }
}

UNDEFINED_VARIANT

When it occurs: A style expression specifies a variant key or value that does not exist in the style preset.

Common causes:

  • Typo in variant key or value
  • Using a variant not defined in the style
  • Case sensitivity issues

How to fix:

json
// Error: UNDEFINED_VARIANT for "xlarge" in style "button"
{
  "styles": {
    "button": {
      "variants": {
        "size": { "sm": "...", "md": "...", "lg": "..." }
      }
    }
  },
  "view": {
    "props": {
      "className": {
        "expr": "style",
        "name": "button",
        "variants": { "size": { "expr": "lit", "value": "xlarge" } }
      }
    }
  }
}

// Fixed: Use valid variant value
{
  "variants": { "size": { "expr": "lit", "value": "lg" } }
}

Compile-Time Warnings

Accessibility warnings are reported during compilation but do not block output. They help you progressively improve accessibility.

A11Y_IMG_NO_ALT

When it occurs: An img element is missing the alt attribute.

How to fix:

json
// Warning: img without alt
{ "kind": "element", "tag": "img", "props": { "src": { "expr": "lit", "value": "/photo.jpg" } } }

// Fixed: add alt attribute
{
  "kind": "element",
  "tag": "img",
  "props": {
    "src": { "expr": "lit", "value": "/photo.jpg" },
    "alt": { "expr": "lit", "value": "A scenic mountain view" }
  }
}

A11Y_BUTTON_NO_LABEL

When it occurs: A button element has no text content or aria-label.

How to fix:

json
// Warning: button with no accessible label
{
  "kind": "element",
  "tag": "button",
  "props": { "onClick": { "event": "click", "action": "submit" } }
}

// Fixed: add text content
{
  "kind": "element",
  "tag": "button",
  "props": { "onClick": { "event": "click", "action": "submit" } },
  "children": [{ "kind": "text", "value": { "expr": "lit", "value": "Submit" } }]
}

// Alternative: use aria-label for icon buttons
{
  "kind": "element",
  "tag": "button",
  "props": {
    "onClick": { "event": "click", "action": "close" },
    "aria-label": { "expr": "lit", "value": "Close dialog" }
  }
}

A11Y_ANCHOR_NO_LABEL

When it occurs: An a element has no text content or aria-label.

How to fix:

json
// Warning: anchor with no accessible label
{
  "kind": "element",
  "tag": "a",
  "props": { "href": { "expr": "lit", "value": "/about" } }
}

// Fixed: add text content
{
  "kind": "element",
  "tag": "a",
  "props": { "href": { "expr": "lit", "value": "/about" } },
  "children": [{ "kind": "text", "value": { "expr": "lit", "value": "About us" } }]
}

A11Y_INPUT_NO_LABEL

When it occurs: An input, textarea, or select element has no aria-label or aria-labelledby.

How to fix:

json
// Warning: input without label
{ "kind": "element", "tag": "input", "props": { "type": { "expr": "lit", "value": "text" } } }

// Fixed: add aria-label
{
  "kind": "element",
  "tag": "input",
  "props": {
    "type": { "expr": "lit", "value": "text" },
    "aria-label": { "expr": "lit", "value": "Search query" }
  }
}

A11Y_HEADING_SKIP

When it occurs: Heading levels are skipped (e.g., h1 followed by h3).

How to fix:

json
// Warning: skipping from h1 to h3
[
  { "kind": "element", "tag": "h1", "children": [...] },
  { "kind": "element", "tag": "h3", "children": [...] }
]

// Fixed: use sequential levels
[
  { "kind": "element", "tag": "h1", "children": [...] },
  { "kind": "element", "tag": "h2", "children": [...] }
]

A11Y_POSITIVE_TABINDEX

When it occurs: An element has a positive tabindex value, which disrupts natural tab order.

How to fix:

json
// Warning: positive tabindex
{
  "kind": "element",
  "tag": "button",
  "props": { "tabindex": { "expr": "lit", "value": 5 } }
}

// Fixed: use 0 (natural order) or -1 (programmatic focus only)
{
  "kind": "element",
  "tag": "button",
  "props": { "tabindex": { "expr": "lit", "value": 0 } }
}

A11Y_DUPLICATE_ID

When it occurs: Multiple elements share the same literal id value.

How to fix:

json
// Warning: duplicate id "header"
[
  { "kind": "element", "tag": "div", "props": { "id": { "expr": "lit", "value": "header" } } },
  { "kind": "element", "tag": "div", "props": { "id": { "expr": "lit", "value": "header" } } }
]

// Fixed: use unique ids
[
  { "kind": "element", "tag": "div", "props": { "id": { "expr": "lit", "value": "main-header" } } },
  { "kind": "element", "tag": "div", "props": { "id": { "expr": "lit", "value": "sub-header" } } }
]

Debugging Tips

  1. Read the full error message: Error messages include the location and context of the issue.
  2. Check spelling: Most errors are caused by typos in names.
  3. Verify declarations: Ensure all state, actions, and components are properly declared before use.
  4. Use a JSON validator: Make sure your JSON is valid before running through Constela.
  5. Start simple: Build your UI incrementally, testing after each change.