Reference table of AxiTrace validation errors - cause and the correct payload fragment for each, including numeric-string and bare-scalar-price leniency added 2026-08.

Troubleshooting: Common Validation Errors

Every rejected request returns its reason as the HTTP 400 response body, and - since the error logging fix described below - is also recorded in Event feed → Errors of your workspace, so you don't have to reproduce a failure locally to see why it happened.

Every Rejection Is Now Logged to the Errors Tab

As of 2026-08, every validation failure across /track and the /v1/* endpoints is recorded to the workspace's Errors tab (Event feed) - not just a subset of code paths. If a request 400s, check there first: the logged entry includes the error message, the offending payload, and the source IP/User-Agent.

Since 2026-08: Numeric Strings and Bare Scalar Prices Are Accepted

Two constraints that used to reject perfectly reasonable data were relaxed in 2026-08. If you're reading this from an older deployment or an older cached copy of this page, note that the examples below describe the current (post-2026-08) behavior:

  • Numeric strings are now accepted anywhere a number is expected - quantity, price, and Money amount fields all accept either a JSON number (1) or a numeric string ("1"), which is what browsers and HTML form inputs naturally send. Non-numeric strings ("abc") are still rejected.
  • A bare scalar is now accepted wherever a Money object is expected - a transaction's revenue, value, discountAmount, and each product's finalUnitPrice/regularPrice/discountPrice/ netUnitPrice can be sent as a plain number (99.9) instead of {"amount": 99.9, "currency": "PLN"}. When sent as a bare scalar, the field has no currency of its own - it's backfilled from revenue.currency before the currency-consistency check runs, so cross-currency mismatches are still caught. Values that are neither an object nor a number/numeric string are still rejected.

One sharp edge: the backfill source is revenue.currency itself. If revenue is sent as a bare scalar too, there is no currency to backfill from - give revenue its currency explicitly (as an object, or make sure at least one Money field in the payload carries a currency) rather than relying on every field defaulting.

Error Reference

Error message Cause Correct payload fragment
label is required page.view, product.view, product.addToCart, and form.submit all require a top-level label, even though it's not persisted. {"label": "Products Page", ...}
client must have at least one identifier (customId, id, uuid, or email) Every event needs a way to attribute it to a visitor. An empty or missing client object fails this on every endpoint that requires one. "client": {"customId": "vt_vid-cookie-value"}
params.sku: expected a non-empty string, got null. Example: {...} product.view and product.addToCart both require params.sku. Missing it, or sending an empty string, triggers this. "params": {"sku": "PROD-001", ...}
params.quantity: expected a number, got string "abc". Example: {...} params.quantity (addToCart) must resolve to a number. A JSON number (2) or a numeric string ("2") both work as of 2026-08 - this error means the value is neither, e.g. free-text. "params": {"sku": "PROD-001", "quantity": 2} (or "quantity": "2")
must be a Money object ({"amount":...,"currency":...}) or a bare number, got: [...] A field expecting Money (revenue, value, discountAmount, finalUnitPrice, etc.) received something that is neither an object nor a number/numeric string - an array, a boolean, or malformed JSON in that position. "revenue": {"amount": 99.99, "currency": "USD"} or, since 2026-08, the shorter "revenue": 99.99 (currency then inherits from the transaction where applicable)
value.currency: expected "USD" (must match revenue.currency), got "EUR". Example: {...} All monetary fields in one transaction must share a single currency. This is unaffected by the 2026-08 leniency change - mixed currencies are still rejected outright, they're just now reported with the expected vs. actual currency instead of a generic message. Use the same currency in revenue, value, discountAmount, and every product's finalUnitPrice
source: expected one of WEB_DESKTOP, WEB_MOBILE, MOBILE_APP, POS, MOBILE, DESKTOP, got string "web". Example: {...} source on a transaction must be one of the six accepted enum values, exactly (case-sensitive). Anything else - including a plausible-looking value like "web" or "online" - is rejected. "source": "WEB_DESKTOP"
paymentInfo.method: expected a non-empty string, got string "". Example: {...} paymentInfo.method is required and must be non-empty. There is no fixed enum for it - CASH, CARD, PAYPAL, STRIPE, etc. are all accepted, it just can't be missing. "paymentInfo": {"method": "CARD"}
products array must contain at least one item. Example: {...} An empty or missing products array on a transaction. "products": [{"sku": "PROD-001", "name": "Widget", "finalUnitPrice": {"amount": 99.99, "currency": "USD"}, "quantity": 1}]

See the full field-by-field reference on the Transaction event page, or the corrected HTTP API examples for every other endpoint.