Transport errors
Transport errors use a standard HTTP status code and a JSON body of the form:Calculation errors
A calculation that cannot complete returns an HTTP200 with status: "error" in the body and an errors array — one entry per problem. Each entry has:
code— a stable, machine-readable identifier for the failure. Branch on this, not onmessage. The full set is listed below.message— an English description template containing numbered%argN%placeholders. It is not pre-filled; substitute theargsbefore displaying it (see Building the message).args— a positional array of string values for the%argN%placeholders inmessage(%arg0%→args[0],%arg1%→args[1], and so on). Read them directly when you need the raw values, such as the unit names. See Building the message.offset— present only oninput.syntax_error: an integer, the zero-based character offset of the error within the equation. It is a caret position between characters —0is before the first character,1is after the first,2after the second, and so on.missing— when the calculation is blocked on inputs, the variables you could supply to continue, grouped as alternatives. See Missing inputs.
args, offset, and missing are each conditionally included — present only when the error uses them, and omitted (never null) otherwise. A consumer must not assume the keys exist.
An incompatible-units error, for example, carries the offending units in args, to substitute into the message template:
Building the message
message is a template, not a finished string. Each placeholder is a numbered token %argN% (zero-indexed), filled from args by index — %arg0% is replaced with args[0], %arg1% with args[1], and so on (the reference client matches /%arg(\d+)%/g):
- If
argsis absent or empty, rendermessageas-is — it has no placeholders to fill. - Replace each
%argN%withargs[N]. The values are already strings in the response. - Match by index, not order of appearance:
%arg1%always meansargs[1], even if it appears before%arg0%in the text. - If a placeholder’s index has no matching value (
Nis at or beyond the length ofargs), leave the literal%argN%token in place — do not blank it.
args and ignore message. The same substitution applies to every error, engine- or request-originated.
Missing inputs
When an error is blocked on inputs,missing lists the variables you could supply to continue. It is an array of option groups — each inner array is one set of variables that must be supplied together to unblock the calculation. More than one group means there are alternative ways to proceed. Read missing as: provide every variable in any one group, then retry.
Each entry is a fully formed variable object — id, key, title, description, and a display render snapshot (the same display shape as a calculation result) — but with no value, since these are candidates you can supply, not resolved values.
down_payment and loan_term while another asks only for loan_amount — satisfying either group (all of its variables) lets the calculation continue.
Calculation error codes
Codes are namespaced by category —input.* for a malformed or under-specified request, calculation.* for a valid request the system cannot solve, and math.* for an undefined numeric result. Branch on the exact code.
Input errors — the request is malformed or under-specified:
input.missing_calculate_target and input.unknown_calculate_target are distinct codes: the first means no target was named in the request; the second means the named target is not a variable in this domain.
Math errors — a numeric result is undefined or unrepresentable:

