Error Codes
A failed tool call comes back as:
<CODE>: <message> (hint: <one-line guidance>)
The code is stable and machine-readable — branch retry logic on it. The hint is one sentence of self-correction guidance, for a human.
Query
AREA_REQUIRED — every query must name one area. Add (area=<snake_case>)
or "$area": "<snake_case>". From geocode it means something else: that tool
takes an area parameter and has no directive syntax at all, so pass area,
name a state in the text itself, or resolve the area first with
list_areas(filter: "<place name>").
AREA_NOT_FOUND — no such area here. The message lists up to five close
candidates; list_areas is authoritative. Names are snake_case and
lower-case (new_york, not New York).
SYNTAX_INVALID — bracket syntax would not parse: missing bracket,
unknown element type, malformed operator. See knowhere://docs/query.
INVALID_JSON — the query starts with { but is not valid JSON. Check
trailing commas and quoting, or rewrite in bracket syntax.
UNSUPPORTED_DIRECTIVE — a top-level $key that is not $type, $area,
$bb, $around, $id, or $and. Tag filters use plain keys, no $.
UNSUPPORTED_OPERATOR — an unknown tag operator, or $regex with
modifiers. Operator list is in knowhere://docs/query.
INVALID_OPERATOR_VALUE — right operator, wrong value type: $in with a
non-array, $exists with a non-boolean, $gt with a string.
INVALID_BOUNDING_BOX — not an array, not a multiple of four
coordinates, or inverted. Use [minLon, minLat, maxLon, maxLat] with
min <= max.
INVALID_COORDINATES — latitude outside [-90, 90], longitude outside
[-180, 180], or NaN/Inf. Check the ordering too: geometry is
longitude first.
QUERY_TOO_LONG — the generated SQL passed 1,000,000 characters. Narrow
with more specific filters, a smaller area, or a bounding box.
QUERY_TIMEOUT — same fix. count_only and a tight (bb=…) are the
cheapest narrowings.
TOO_MANY_RESULTS — the query matched more rows than the server will hold
in memory at once. It is refused rather than truncated: truncation would hand
back a wrong answer that reads exactly like a complete one. Narrow the area,
add tag filters, or split the work by bounding box.
The cap depends on which tool raised it. From runtime's query.execute and
query.union it is 50,000, and query.count() answers the how-many question
with no cap at all. From near it is 100,000 per side, the message names
which side overran, and there is no count-only equivalent — narrow the find
or near query itself.
QUERY_EXECUTION — the SQL engine could not run it. Usually server-side;
retry after adjusting, and if it persists the server may be misconfigured.
QUERY_UNKNOWN — a category unknown to the classifier. Read the message.
Routing
Behaviour behind these is in knowhere://docs/routing.
NO_ROUTING_DATA — the area has no road graph, because it was built with
routing disabled. Straight-line tools still work.
NO_ROUTE — both ends snapped, but nothing connects them. Almost always
different areas; routing never crosses an area boundary. On profile: "foot"
it can also be an isolated footway, which is common in OSM.
NO_ROAD_NEARBY — nothing usable within max_snap_meters (default
2000). Usually the coordinate is not in the area you named, and the message
says which area does contain it — re-run against that one rather than raising
the ceiling.
BEYOND_RANGE — a route exists but is longer than the mode allows.
Walking is capped (max_walk_meters, default 10,000, max 25,000). Raise the
cap or use profile: "car".
NO_ISOCHRONE — reachability was asked for over the driving graph. It is
walking-only, and this refuses rather than returning a search space that
looks like a reachable set. For driving, name destinations and use
drive_times.
REACH_TOO_LARGE — max_walk_meters above the 5 km reachability cap.
Lower it, or use route with profile: "foot" for one long trip.
NO_PLACE_NEARBY — from reverse_geocode, nothing named within the
radius; open water and wilderness genuinely have no answer, otherwise raise
max_meters (widening is cheap — the search starts at 30 m). From geocode,
nothing matched the text: house numbers match exactly, and OSM has roughly a
quarter of US house numbers, so retry without the number for a street-level
answer. A named feature needs at least 3 characters to be searched at all.
When most — not all — of a name's words match something, geocode returns it
flagged partial_name: true instead of failing; a query that still gets this
error shares too little with anything indexed for even a flagged guess.
geocode searches one area at a time, so a place that plainly exists but is
not found is often in another area — list_areas with the name as filter
reports which one holds it.
Runtime
PAYLOAD_TOO_LARGE — the exported payload exceeded the size cap after
JSON encoding. Aggregate, slice, or project inside the script — counts, a tag
histogram, the top N — instead of the full result set.
PAYLOAD_NOT_SERIALIZABLE — the payload holds a function, undefined, or
a circular reference. A Result's name/asBound/asPoint/asFeature are
methods: call them.
UNKNOWN_PROPERTY — the script read a property a Result does not have
(r.lat exists; r.minLat and r.center do not). In plain goja that read
would return undefined and flow NaNs silently into the payload; a Result
throws instead, and the error carries the full roster of properties and
methods plus a did-you-mean. Feature-test with ("x" in r) — the in
operator never throws. Tag values are exempt: r.tags.anything is an
ordinary object access and undefined for an absent tag is normal.
Zillow
ZILLOW_BAD_INPUT — empty bounding_boxes, or a box that is not exactly
[minLat, minLon, maxLat, maxLon]. Latitude first — this tool is the
exception.
ZILLOW_UPSTREAM — the upstream request failed or returned an unexpected
shape. Usually transient: retry, or narrow the boxes.
Correction loop
- Call the tool.
- If the response starts with
<CODE>:, branch on the code. AREA_NOT_FOUND— retry with the closest candidate, orlist_areas.SYNTAX_INVALID/INVALID_JSON— rereadknowhere://docs/query.INVALID_COORDINATES/INVALID_BOUNDING_BOX— check[lon, lat]order and range.QUERY_TIMEOUT/QUERY_TOO_LONG/TOO_MANY_RESULTS— narrow, or usetag_valuesto find a more selective filter; for a count alone usequery.count().NO_ROUTE/NO_ROAD_NEARBY— check both ends are in the same area;NO_ROUTING_DATA— fall back tonear.PAYLOAD_TOO_LARGE— export less.
Related
knowhere://docs/query— syntax reference.knowhere://docs/routing— what the routing limits are and why.knowhere://docs/schema— coordinate and area-name conventions.