Skip to content

Errors & Recovery

Errors are designed to be agent-actionable: every failure carries a kind plus, where relevant, the offending field, a recovery hint, and structured extra data. Agents shouldn't need to parse prose to recover — and neither should your automation.

Error kinds

Kind Meaning Right response
VALIDATION A field failed a format/range rule Fix the named field, retry
MISSING_FIELD A required field/parameter is absent Supply it (e.g. build-context needs site or region)
REF_NOT_FOUND An id doesn't exist or isn't in your tenant Don't retry the id — look the entity up by name. Foreign and nonexistent ids are deliberately indistinguishable
CONFLICT_STATE The load's current status doesn't allow this action Read extra.allowed_transitions and relay them; don't retry the same transition
OUT_OF_RANGE A numeric bound was violated (quantity, limit, …) Adjust the value
AUTH_REQUIRED No valid credential reached the backend Re-authenticate / check the key
AUTH_AMBIGUOUS Both an OAuth bearer and an API key were sent Send exactly one credential

Validation errors vs. warnings

validate_load separates the two explicitly:

  • errors[] block creation. Each entry names the field path (e.g. assignments[0].line_items[0].tank_id) and why it failed.
  • warnings[] don't block — they flag judgment calls for a dispatcher: window_short, quantity_unusual, tank_overfill, driver PTO conflicts, off-allowlist equipment, unusual tank↔product pairings. Creating over warnings requires explicit acknowledgment.

Gate errors (not backend errors)

These come from the MCP server's own write gates, before any backend call:

Message contains What happened Recovery
"unknown or expired" The validation/confirm token aged out (15 min) or the server restarted Re-run validate_load (or the preview call) and use the fresh token
"payload changed since it was validated" The draft was mutated after validation Re-validate the current payload
"declined by the user" The human said no at the confirmation prompt Adjust the plan per their feedback; don't retry unchanged
"warning(s). Surface them" Warnings weren't acknowledged Show the user, then pass acknowledge_warnings=true
"not enabled for this account" The server is in allowlist mode and your organization isn't enabled Contact FolioX

Partial failure

Bulk creates return per-item results. success_count < total_count with entries in errors[] means some loads were created and some weren't — the response is explicit about which, and agents are instructed to report exactly that rather than a blanket success.

Timeouts & retries

  • Reads are safe to retry as-is.
  • create_load retries are idempotent (the idempotency key replays the original result — it will not double-create).
  • Mutation executes are not blindly retryable: re-run the preview phase to get a fresh token against current state.