Error codes
Everything xoong finds has a stable code, a place, a message that says what is wrong, and a fix. This page lists every code with the explanation that the MCP tool explain_error gives: the page is made from the same table, so they cannot differ. XO2xx codes come from xoong check, and XO1xx codes from xoong doctor and xoong sync.
What a finding looks like
An error makes the command exit with 1; a warning is printed and does not. The message says what is wrong, and fix: says what to do. The same finding, as text and as the JSON that --format json prints:
screens/people.html:2:11 error XO201 unknown operation "deletePersn" (closest: "deletePerson")
fix: Use "deletePerson"{
"level": "error",
"code": "XO201",
"file": "screens/people.html",
"line": 2,
"column": 11,
"message": "unknown operation \"deletePersn\" (closest: \"deletePerson\")",
"fix": "Use \"deletePerson\""
}Editors show the same message and fix on the line (Editor support), and an assistant reads them through the MCP server. The first number after XO is the tool: 1 for the OpenAPI document, 2 for your screens.
xoong check (XO2xx)
Operations in screens
A name in xo-click, xo-submit, get or op that is not in the synced API, or an operation used the wrong way round: a click that calls a read, a view that reads a write, and in JavaScript load on a write or mutate on a read.
| Code | What it means and how to fix it |
|---|---|
XO201 | An operation name in xo-click, xo-submit, <xo-view get> or <xo-form op> does not exist in the synced API. Use the closest name the message gives, or run xoong sync if the API changed. |
XO202 | xo-click calls a GET operation. Reads are declared with <xo-view get="...">; xo-click is for mutations. |
XO203 | <xo-view get> uses an operation that is not GET. Use a GET operation for reading and xo-click/xo-submit for writes. |
XO204 | client.load()/query() were given a write operation, or client.mutate()/stream() a GET. Reads: load/query. Writes: mutate. |
Path parameters
A view whose operation has a {param} in its path and no p-param to fill it.
| Code | What it means and how to fix it |
|---|---|
XO210 | The view's operation has a path parameter such as {id}, but the view has no p-id attribute. Add p-id="..." or set view.params in JavaScript. |
Forms and expressions
xo-submit away from a form, a form outside an xo-view (it never binds), an xo-each, xo-if or xo-body with no path.
| Code | What it means and how to fix it |
|---|---|
XO220 | xo-submit is only valid on a <form>. Move the attribute to the form element. |
XO221 | xo-each, xo-if or xo-body has no path. Give it one, for example xo-each="items". |
XO222 | <form xo-submit> must be inside an <xo-view>, otherwise it never binds. Wrap it in <xo-view> (without get is fine). |
Unknown names
An xo-* element or attribute that xoong does not define. Nearly always a typo; the message names the closest one.
| Code | What it means and how to fix it |
|---|---|
XO230 | An xo-* element or attribute that xoong does not define, usually a typo. The message names the closest valid one. |
Accessibility and images
A button without a name, a click that a keyboard cannot reach, an xo-image without alt, an img whose src is bound inside a view.
| Code | What it means and how to fix it |
|---|---|
XO240 | A button or link triggered by xo-click has no accessible name. Add visible text or aria-label. |
XO241 | xo-click is on an element that keyboards cannot reach. Use a <button>, or add role="button" and tabindex="0". |
XO242 | <xo-image> has no alt attribute. Describe the image, or write alt="" when it is only decoration. |
XO243 | An <img> whose src or srcset has {data} inside an <xo-view> is requested by the browser with the literal text before the data is bound. Use <xo-image src="{path}" alt="..."> instead. |
Tables, pagers, generated forms and selection
A table or pager asking for sorting, paging or filters that the operation does not offer, or sitting outside a view; a generated form with nothing to generate; xo-select and xo-selected used wrongly.
| Code | What it means and how to fix it |
|---|---|
XO250 | <xo-table sortable> needs a sort query parameter on the view's operation, and page-size (and every <xo-pager>) needs limit and offset. Add them to the API or remove the attribute or the pager. |
XO251 | <xo-table> and <xo-pager> must be inside an <xo-view get="...">, which supplies their data. |
XO252 | <xo-form op> found no simple request fields to generate. Write the <form xo-submit> by hand. |
XO253 | A filter box of <xo-table filters="..."> sets a query parameter of the same name, and the view's operation does not declare it. Add the parameter to the API or remove the filter. |
XO254 | xo-selected only makes sense on an xo-click button, and xo-select on a checkbox. Move the attribute. |
XO255 | This operation has no request schema (for example a multipart body), so <xo-form> can only draw simple fields, and the operation requires nested objects, arrays or unions: the generated form can never satisfy the server. Write the <form xo-submit> by hand. |
Routes and layouts
A route path that is missing, malformed or repeated, a layout that is not declared or has no outlet, a route parameter that the route does not have.
| Code | What it means and how to fix it |
|---|---|
XO260 | A route path must start with "/" (or be "*" for not found) and each path may be declared once per router. Write xo-route="/users/:id". |
XO261 | layout="x" on a route (or layout) names a layout that is not declared in the same <xo-router>. Declare <template xo-layout="x">, or use the closest name the message gives. |
XO262 | A layout template needs one element with xo-outlet where the route content is shown, for example <main xo-outlet>. |
XO263 | p-x=":name" reads a route parameter: it only works inside a <template xo-route="..."> whose path contains :name. Fix the name, or use a fixed value or p-x="?query". |
Attributes in the wrong place
An attribute that does nothing where it stands, a value outside its set or malformed, a name that the operation does not have, an attribute outside the element that gives it meaning.
| Code | What it means and how to fix it |
|---|---|
XO270 | An attribute that does nothing where it is. xo-then, xo-notice, xo-confirm, xo-body, xo-optimistic and xo-with tune an action, so they need xo-click or xo-submit on the same element (xo-with also works with xo-add); xo-keep needs xo-submit; xo-confirm-title, xo-confirm-ok, xo-confirm-cancel and xo-confirm-kind need xo-confirm; <xo-dialog size> needs heading. Move the attribute onto the element that has the action, or remove it. |
XO271 | An attribute that takes one of a fixed set of values has another one, and the runtime silently uses the default. xo-confirm-kind: danger, warning, info, success. <xo-dialog size>: sm, wide, full. Use the closest value the message gives (call explain_syntax with the attribute to see them all). |
XO272 | A value with a syntax of its own is malformed, and the runtime ignores it. xo-with and xo-optimistic: "field=value,other={path}". xo-param: "name=value", "name+=n", "name-=n" or "name~=value" (just the name on an <input>/<select>). xo-move: "path:up" or "path:down". xo-select: no value on a row checkbox, "all:<list>" on the header one. |
XO273 | xo-open="#id" must name an <xo-dialog> (the id is not in this file, or it is on another element), and xo-close only closes the <xo-dialog> it is inside. Put the id on the <xo-dialog>, and the close button inside it. |
XO274 | xo-with (and the field name of xo-selected="ids") adds a field to the request body, and the operation has no such field (or no request body at all). Use list_operations to see the body fields; the message names the closest one. |
XO275 | xo-param sets a view parameter, and the view's operation does not take it as a path or query parameter, so the request does not change (the value is still available as {name} in the view). Add the parameter to the API, or remove xo-param. |
XO276 | An attribute outside the element that gives it meaning: xo-route and xo-layout belong on a <template> that is a direct child of <xo-router>; xo-tab inside <xo-tabs>; xo-menu-trigger inside <xo-menu>; xo-guard on a <form xo-submit>; xo-add, xo-remove, xo-move and xo-drag inside a <form xo-submit>. |
xoong doctor and xoong sync (XO1xx)
The document and its identity
No paths at all, or an x-xoong-id that names nothing or disagrees between the schemas of one entity.
| Code | What it means and how to fix it |
|---|---|
XO100 | The OpenAPI document has no "paths". Add a paths object (or declare webhooks/components only if that is intended). |
XO101 | x-xoong-id names a property that the schema does not have. Name existing properties or remove it. |
XO102 | Two schemas that are one entity (a hint or x-xoong-entity maps them together) use different id properties. Use the same id property for every schema of one entity. |
Operations
A missing or repeated operationId, an undeclared path parameter, and what the document asks for that xoong does not do (a required header, cookies, HEAD or OPTIONS, servers, a query style).
| Code | What it means and how to fix it |
|---|---|
XO110 | An operation has no operationId, so xoong made one up (the message says which). Add an operationId: it is the stable name used in xo-click, <xo-view get> and the typed client. |
XO111 | Two operations have the same operationId. Make them unique. |
XO112 | A {param} of the path is not declared under parameters with in: path. Declare it so the type is known. |
XO113 | The document asks for something that changes what a call needs or does, and xoong does not apply it (one finding per kind, naming a few operations): a required header parameter (such as X-Tenant-Id: send it with configure({ headers: () => ({ ... }) })), a cookie parameter (the browser sends its own; configure({ credentials: 'include' }) for another origin), HEAD, OPTIONS or TRACE operations (not generated: use fetch()), servers (requests go to the page's origin: configure({ baseUrl })), or a query parameter with explode: false, deepObject or pipeDelimited/spaceDelimited (xoong sends name=a&name=b and writes no object: pass the text the server expects). operations.json is not changed by any of these. |
Responses
A GET without an application/json success schema, so no types or cache can be made.
| Code | What it means and how to fix it |
|---|---|
XO120 | A GET operation has no application/json success schema, so no types or cache can be generated for it. Describe the response. |
Error responses
An operation that documents no 4xx, 5xx or default response.
| Code | What it means and how to fix it |
|---|---|
XO130 | An operation documents no error responses. Document 4xx/5xx or default (application/problem+json) so errors have a shape. |
Entities
A schema with an id-like property that is not treated as an entity, so its records are not shared between screens.
| Code | What it means and how to fix it |
|---|---|
XO140 | A schema has an id-like property but is not treated as an entity, so its records are stored inline and not shared between screens. If instances repeat across responses, add the hint { "schemas": { "Name": { "id": "prop" } } } or x-xoong-id; otherwise ignore. |
References
A $ref that points nowhere, or outside the document.
| Code | What it means and how to fix it |
|---|---|
XO150 | A $ref points to something that does not exist in the document. Define the target or remove the reference. |
XO151 | An external $ref is not resolved by xoong. Bundle the document so every reference is local (for example with redocly bundle). |
Unions
Members of a union that cannot be told apart, in a response or in a request body.
| Code | What it means and how to fix it |
|---|---|
XO160 | A response contains a union of entities that cannot be told apart, so they are not stored in the shared entity store. Give the members a property with one fixed value each, or an OpenAPI discriminator. |
XO161 | A union in a request body cannot be told apart, so a generated form draws it as free-form. Add a discriminator, or a property with a different fixed value (const or one-value enum) in each member. |
The hints file
A key of xoong.hints.json that does nothing, or a hint that names something the document does not have.
| Code | What it means and how to fix it |
|---|---|
XO170 | The hint idempotencyKeys.<operationId> names a field that the request body does not have. Name an existing body property or remove the hint. |
XO171 | xoong.hints.json has a key xoong does not know (usually a typo), so it does nothing. The keys are idNames, schemas, unwrap, idempotencyKeys and fields. |
XO172 | A hint refers to something the document does not have: a fields key must be "Schema.property" of an existing schema, and idempotencyKeys must name an existing operationId. Use the closest name the message gives. |
See also: Command line · MCP server · Editor support