coord_out_of_bounds | 400 | The coordinate is outside both supported US regions. | Accept the primary us_envelope from /v1/meta/fields or the Western Aleutian rectangle (lat ∈ [51, 54], lng ∈ [172, 180)). |
no_fields_requested | 400 | /v1/fetch called with neither fields nor preset. | Provide at least one of the two. |
fields_unknown | 400 | One or more requested field names are not in the catalog. | Hit /v1/meta/fields, pick valid names. |
fields_too_many | 400 | Resolved field set (post-preset-expansion) exceeds 50. | Drop the preset, split into multiple calls, or remove explicit fields. |
ask_upstream_rate_limited | 429 | /v1/ask: the LLM API rate-limited the call. | Retry with backoff (retryable: true). |
ask_upstream_unreachable | 502 | /v1/ask: could not reach the LLM API. | Retry with backoff (retryable: true). |
ask_upstream_error | 502 | /v1/ask: the LLM API returned an error. | Retry only if retryable: true (upstream 5xx). |
ask_timeout | 504 | /v1/ask exceeded the 110 s end-to-end deadline. | Retry; persistent timeouts mean a degraded upstream source. |
ask_answer_incomplete | 502 | /v1/ask, /v1/ask/stream, /v1/ask-site: the model did not return a complete answer — it ran out of output budget mid-answer, or omitted a required part of it. | Retry (retryable: true). The condition is stochastic, so the same question usually succeeds on the next attempt. The credits are refunded (best-effort — the refund is fail-open, so in the rare case our counter store is unreachable at that moment the charge can stick). On the streaming endpoint this arrives as a terminal error frame and no final frame, so any text already streamed should be discarded rather than shown as the answer. |
ask_question_refused | 422 | /v1/ask, /v1/ask/stream, /v1/ask-site: the model declined to answer the question. | Do not retry (retryable: false) — unlike ask_answer_incomplete this is deterministic for the same input, so an identical retry fails identically. Rephrase the question. |
invalid_locator | 422 | /v1/fetch, /v1/ask, and the MCP tools: the request gave BOTH a coordinate and an address, or neither, or only half a coordinate. /v1/field-requests uses the same code when an example_locations entry doesn’t supply exactly one of address, lat+lng, or polygon. | Send exactly one locator per location. |
address_form_unsupported | 422 | /v1/geocode, /v1/fetch, /v1/ask, /v1/lookup, /v1/field-requests: the address is a PO box, carrier route (RR/HC), military APO/FPO, or general delivery — a mail destination, not a place. | Ask the user for a street address. Reformatting cannot help; these have no coordinate in principle. Costs nothing — rejected before the provider is called. |
address_not_found | 404 | /v1/geocode, /v1/fetch, /v1/ask: the provider processed the address and has no match. | Check for a typo; do not retry. |
address_too_coarse | 404 | /v1/geocode, /v1/fetch, /v1/ask: resolved only to a ZIP/city/county/state centroid, not a property. /v1/lookup returns this as a no_match disposition (reason: "address_too_coarse"), not this HTTP error; /v1/field-requests returns it as a 422 (the location is one field of a larger body) — see each endpoint’s page. | Ask the user for a street number. Retrying cannot help — the provider’s answer is stable. |
geocode_busy | 429 | /v1/geocode, /v1/fetch, /v1/ask: the per-worker overload gate shed the request. | Retry after Retry-After (2 s). |
geocode_upstream_error | 502 | /v1/geocode, /v1/fetch, /v1/ask, /v1/lookup: the provider returned 5xx or dropped the connection. | Retry after Retry-After (2 s). |
geocode_timeout | 504 | /v1/geocode, /v1/fetch, /v1/ask, /v1/lookup: the primary provider AND the fallback both exceeded their deadlines. | Retry after Retry-After (5 s). |
geocode_forbidden | 503 | /v1/geocode, /v1/fetch, /v1/ask, /v1/lookup: the geocoding provider recognized the credential but refused the request — almost always a usage/spend limit or a missing plan entitlement. | Not a bad key. Check the provider’s usage limit first; the daily cap resets at midnight EST, so Retry-After is an hour. The upstream’s own message is included in message. |
geocode_unconfigured | 503 | /v1/geocode, /v1/fetch, /v1/ask, /v1/lookup: the service is missing its provider credential. | Not a caller problem and not retryable — report it. We deliberately do NOT degrade to the free lower-precision tier, which would look healthy while serving ~2,872 m rural error. |
resolve_coord_bounds | 422 | /v1/lookup only: coordinate is outside any plausible bound, including a swapped-lat/lng pair. | Check your lat/lng order. |
resolve_invalid_input | 422 | /v1/lookup only: input didn’t parse as an address, "lat,lng" coordinate, or APN-shaped token. | Fix the input format. |
resolve_busy | 429 | /v1/lookup only: its own per-worker overload gate (separate from geocode_busy). | Retry after Retry-After (3 s). |
resolve_timeout | 504 | /v1/lookup only: did not complete within the endpoint’s deadline (geocode leg + parcel leg + enrichment). | Retry after Retry-After (5 s). |
invalid_request | 422 | /v1/proximity only: the body fails the schema — a bad field, an unknown op, or a per-request limit (origins × destinations, address-form locators). Uses the standard error object, with pydantic’s per-field detail under errors. | Fix the keys named in errors; for a limit breach, split the request. |
unresolvable_input | 422 | /v1/proximity only: every locator for a required role (an op’s origin(s), or screen’s anchors) failed to resolve. Carries role, unresolved_count, an unresolved sample naming each locator, what it matched instead and at what accuracy_type, and caller_guidance. | Read unresolved — a place tier means you sent a name or a bare street, so add city+state or use a coordinate. See Diagnosing unresolvable_input. |
unknown_set | 422 | /v1/proximity only: nearest’s set isn’t one of the six curated sets. | Use @airports, @substations, @power_plants, @rail, @ports, or @urban_areas. |
shed_too_large | 422 | /v1/proximity only: labor_shed’s geometric annulus exceeded 3,000 tracts. | Shrink minutes. |
proximity_request_exceeds_budget_share | 422 | /v1/proximity only: one request would reserve more than its allowed share of the shared, fleet-wide monthly driving-matrix budget. Distinct from proximity_budget_exhausted — the pool has room, this single call is too big a bite of it. | Shrink the request as message directs: split the locator lists, or for labor_shed (which has no batch parameter) reduce minutes. message names the ceiling in driving calcs (currently 3,500 per request). Not retryable — the same body fails identically every time — and note it IS billed, since it is raised after metering. |
proximity_busy | 429 | /v1/proximity only: its own per-worker overload gate (separate from geocode_busy/resolve_busy). Never billed. | Retry after Retry-After (5 s). |
proximity_budget_exhausted | 503 | /v1/proximity only: the shared, fleet-wide monthly driving-matrix budget is exhausted. | Retry after Retry-After (3600 s). |
proximity_data_unavailable | 503 | /v1/proximity only: a backing local asset (a curated set, or the labor-shed tract table) isn’t available right now. | Retry with backoff. |
proximity_unconfigured | 503 | /v1/proximity only: the service is missing its routing-provider credential. | Not a caller problem and not retryable — report it. |
upstream_transient | 502 | /v1/proximity only: the routing provider had a transient failure (5xx, connection drop, rate limit). | Retry with backoff. |
upstream_auth | 502 | /v1/proximity only: the routing provider rejected the credential or the request. | Not retryable — report it. |
upstream_error | 502 | /v1/proximity only: the catch-all for a routing-provider failure the specific codes above don’t name — a malformed distance-matrix response, or a status the provider isn’t documented to return for pre-validated coordinates. | Retry with backoff. Persisting is worth reporting: for coordinate-only input this shape shouldn’t occur. |
proximity_deadline_exceeded | 504 | /v1/proximity only: the request exceeded the endpoint’s own deadline. Distinct from a routing-provider timeout, which stays upstream_transient. | Retry with backoff; a smaller request (fewer origins × destinations) will also finish sooner. |
invalid_payload | 422 | /v1/field-requests only: the body fails the schema — missing required field, limit exceeded, or an unknown key (rejected, never ignored). Unlike the rest of the API, schema errors on this endpoint use the typed detail shape, with pydantic’s per-field detail under errors. | Fix the keys named in errors. |
context_blob_too_large | 422 | /v1/field-requests: context_blob exceeds 8 KB (UTF-8 bytes). | Shrink the blob. |
location_out_of_bounds | 422 | /v1/field-requests: an example_locations coordinate is outside the US envelope — a swapped lat/lng pair is named as such. | Check coordinate order and coverage. |
invalid_geometry | 422 | /v1/field-requests: polygon isn’t a GeoJSON Polygon/MultiPolygon, or has no coordinates. | Fix the geometry. |
location_unresolved | 422 | /v1/field-requests: an address had no plausible geocode match, or its lone match was in a different city than the one named. | Supply a coordinate or a fuller address. |
idempotency_key_reused | 409 | /v1/field-requests: the idempotency key was already used for a different payload. | Use a new key, or re-send the identical body. |
field_requests_unavailable | 503 | /v1/field-requests: the request store is unreachable. | Retry with backoff. |
field_request_not_found | 404 | GET /v1/field-requests/{id}: no such request under your credential (someone else’s id is also a 404, never a 403). | Check the stored request_id. |