Errors
Estaite MCP tools never throw — failures are returned as a structured error envelope with a stable error code, a human-readable message, and (where useful) a valid_values hint or warnings array.
Error envelope
The tool result has isError: true and a single text-content item containing stringified JSON:
{ "error": "INVALID_BEDROOM_COUNT", "message": "7 is not a valid bedroom count.", "valid_values": [1, 2, 3, 4, 5]}Parse the content[0].text as JSON to read the fields. Always check isError before attempting to parse a normal payload — error responses are not valid tool data.
Codes
| Code | HTTP | Meaning | Emitted by |
|---|---|---|---|
MISSING_QUERY | 400 | query was empty or not a string. | search_estaite_submarkets |
MISSING_OR_INVALID_SUBMARKET_ID | 400 | id missing or non-numeric. | query_estaite_submarket_index, get_estaite_market_snapshot, get_estaite_rent_trends, get_estaite_affordability, get_estaite_comparable_markets |
SUBMARKET_NOT_FOUND | 404 | No data exists for the requested submarket id. | Same set as MISSING_OR_INVALID_SUBMARKET_ID. |
MISSING_ZIP | 400 | zip was not provided. | get_estaite_zip_metrics |
INVALID_ZIP | 400 | zip is not a 5-digit numeric string. | get_estaite_zip_metrics |
ZIP_NOT_FOUND | 404 | No data exists for the requested ZIP. | get_estaite_zip_metrics |
MISSING_CBSA | 400 | cbsa not provided. | get_estaite_cbsa_overview, get_estaite_cbsa_trends |
CBSA_NOT_FOUND | 404 | No CBSA matched, or no months satisfy the filter. | get_estaite_cbsa_overview, get_estaite_cbsa_trends |
INVALID_PROPERTY_TYPE | 400 | property_type is not one of apt, sfr, ct. | get_estaite_zip_metrics, compare_estaite_submarkets, query_estaite_submarket_index, get_estaite_rent_trends, get_estaite_affordability. Tools that don’t throw this (rank, find-by-criteria, comparable-markets) silently fall back to apt. |
INVALID_BEDROOM_COUNT | 400 | bedrooms is outside 1–5. Carries valid_values: [1,2,3,4,5]. | Same set as INVALID_PROPERTY_TYPE. Tools not on the list silently fall back to 2. |
INVALID_BEDROOM_FOR_PROPERTY_TYPE | 400 | apt or ct with bedrooms = 5. | query_estaite_submarket_index only. Other tools that accept those combos return null for the cell. |
INVALID_TREND_PERIOD | 400 | trend_period not one of mom, 3m, 6m, 9m, yoy. Carries valid_values. | query_estaite_submarket_index |
INVALID_METRIC | 400 | metric not one of median_rent, rent_growth, vacancy, affordability, dom. | rank_estaite_submarkets |
MINIMUM_TWO_SUBMARKETS_REQUIRED | 400 | Compare called with fewer than 2 entries. | compare_estaite_submarkets |
TOO_MANY_SUBMARKETS | 400 | Compare called with more than 10 entries. | compare_estaite_submarkets |
INSUFFICIENT_MATCHES | 404 | No supplied submarket matched. Response carries a warnings array of which names failed. | compare_estaite_submarkets |
Non-error empty responses
Some tools return success with empty data when nothing matches — these are not errors:
search_estaite_submarketswith no matches returns{ count: 0, results: [] }.list_estaite_submarketswith restrictive filters returns{ data: [] }.find_estaite_submarkets_by_criteriawith too-narrow criteria returns{ count: 0, data: [] }.
Branch on isError, not on empty arrays.
Transport-level errors
These come from the HTTP / auth / quota layer rather than tool code:
| Status | Meaning |
|---|---|
401 Unauthorized | Missing, malformed, or revoked API key. See Authentication. |
403 Forbidden | Workspace suspended, or direct-origin access without the required edge auth header. |
429 Too Many Requests | Per-second rate limit or monthly quota exceeded. Response includes Retry-After. See Rate limits. |
5xx | Generic upstream failure. Safe to retry with exponential backoff. |
Transport errors arrive as protocol-level errors (raised by the MCP SDK) rather than tool results — your client library typically throws them. Handle them at the session level, not per-tool.