Debugging & Troubleshooting
Troubleshooting iXML is faster when you follow a strict reduction workflow: isolate, reproduce, inspect, and fix. This page provides systematic processes for parser errors, runtime exceptions, and data-shape bugs, along with the full debug namespace for development-time inspection.
Debugging Workflow
- Reproduce the issue with a minimal snippet using
zeysdk run --ixml. - Capture the exact error message and location.
- Reduce by removing branches and variables until the root cause is obvious.
- Fix the minimal case, then rebuild toward the full version.
- Verify the fix works in the original context.
Parser Errors
Parser errors occur before execution. The iXML engine validates XML structure, element names, and attribute names during parsing. Note that error messages show attribute and element names in uppercase — iXML itself is case-insensitive.
Unknown Attribute
ERROR: iXML\ParserException: Unknown attribute "CONDITION" in element "IF"
Cause: Using an attribute that does not exist on the element.
Common cases:
<if condition="...">— Usevalue1,value2,funcinstead.<set var="$name">— Remove the$; it is substitution syntax, not part of variable names.<encode:base64 type="mime">—typeattribute does not exist onencode:base64.
Fix: Check the command's attribute list in the documentation.
Malformed XML
ERROR: iXML\ParserException: expected '>'
Cause: Invalid XML syntax — unescaped characters in attributes, missing closing tags, or mismatched elements.
Common cases:
func="<"— Must befunc="<"(XML requires escaping<and>in attribute values).- Missing closing tag or mismatched nesting.
Unknown Element
ERROR: iXML\ParserException: Unknown element "DB:ISNOT"
Cause: Using a command that does not exist.
Common cases:
<db:isnot>— Does not exist. Use<db:is func="!=">or<db:isnotnull/>.<encode:hex>— Does not exist in the encode namespace.<encode:hmac>— Does not exist. Use<encode:hash algorithm="sha256" key="secret">.<array:count>— Does not exist. Use<size var="count">$array</size>.
Runtime Errors
Runtime errors occur during execution. They can be caught with <try>/<catch>.
Type Errors
Symptom: Unexpected behavior or empty output.
Diagnosis:
<set var="test">42</set>
<typeof var="test" var_result="t"/>
<output>Type: $t</output>
<!-- Output: Type: string -->
Fix: Use <cast> for explicit type conversion:
<cast var="test" type="int"/>
<typeof var="test" var_result="t"/>
<output>Type: $t</output>
<!-- Output: Type: int -->
Common mistake: <set> always creates strings. <set var="x">42</set> creates the string "42", not the integer 42. Use <cast var="x" type="int"/> after setting if you need a numeric type.
Data Shape Inspection
When output is unexpected, serialize intermediate structures to see their actual shape:
<encode:json var="payload" var_result="debug" pretty="1"/>
<output>$debug</output>
Use this before database writes and before final API output to verify the data structure.
Database Errors
Common issues:
- Type mismatch:
contacts.typeissmallint, not a string. Using<db:is field="c.type">Customer</db:is>causes a PostgreSQL type error. - NULL comparison:
<db:is field="c.email">NULL</db:is>does not check for NULL. SQL NULL requiresIS NULLsyntax — use<db:isnull field="c.email"/>. - Access forbidden: System tables like
information_schema.columnsare blocked in ZeyOS.
Defensive Error Handling
Wrap risky operations in <try>/<catch>:
<try>
<decode:json var="data">$body</decode:json>
<catch var="err">
<set var="return">400</set>
<output>Invalid JSON: $err</output>
</catch>
</try>
Debug Commands
The debug namespace provides four commands for development-time inspection. See ZeyOS Platform Services for full documentation.
debug:output
Writes a message to the debug console (separate from application output — you will not see it in zeysdk run --ixml results):
<debug:output>Processing ID: $id, Status: $status</debug:output>
debug:dump
Dumps all variables or a specific variable with recursive structure inspection:
<!-- Dump a specific variable -->
<debug:dump var="contacts"/>
<!-- Dump all variables -->
<debug:dump/>
debug:log
Writes to the debug log file (persisted, unlike console output):
<debug:log>Error processing contact $id: $error_msg</debug:log>
debug:exclude
Temporarily disables a code block without removing it. Unlike XML comments, the code inside is still parsed and validated — so syntax errors in disabled code will still be caught:
<debug:exclude>
<db:delete entity="contacts">
<db:is field="c.status">inactive</db:is>
</db:delete>
</debug:exclude>
Debugging Strategies
Service Endpoint Debugging
When debugging API handlers, check in this order:
- Route and method — Is the correct service being invoked?
- Body decode — Is the request body valid and parsed correctly?
- Validation — Are required fields present and correctly typed?
- Database operations — Are queries returning expected results?
This order prevents misdiagnosing downstream failures caused by upstream issues.
Iterative Reduction
When facing a complex bug, reduce the code iteratively:
<!-- Step 1: Does the basic structure work? -->
<output>Step 1: Start</output>
<!-- Step 2: Does the data load correctly? -->
<db:select var="data" entity="contacts" type="self" limit="1">
<db:fields>c.ID, c.name</db:fields>
</db:select>
<encode:json var="data" var_result="json" pretty="1"/>
<output>$json</output>
<!-- Step 3: Add processing logic back one piece at a time -->
Regression Prevention
After fixing a bug:
- Keep a minimal reproducer snippet.
- Run it again and capture the passing output.
- Document the issue to avoid repeating the same mistake.