---
summary: "Wire declared error recovery hints through to callers on every tool and resource, surface water_dataframe_query's truncation flag as an output field, scope its non-SELECT rejection to what callers can invoke, and drop water_get_series's unreachable site_not_found reason."
breaking: false
security: false
---

# 0.2.2 — 2026-07-19

## Added

- **`table_not_found` and `system_catalog_access` reasons on `water_dataframe_query`** — a SELECT naming a table that isn't staged on the canvas, or reading a system catalog (`information_schema`, `pg_catalog`, `sqlite_master`, `duckdb_*`), now gets its own reason and scoped recovery instead of falling into the generic `invalid_sql`. ([#25](https://github.com/cyanheads/usgs-water-mcp-server/issues/25))

## Changed

- **Every declared `recovery` hint now reaches callers** — every `ctx.fail` call site across the seven tools and the `usgs-water://site/{siteId}` resource passes `ctx.recoveryFor(reason)`, so `error.data.recovery.hint` and the mirrored `content[]` text carry the guidance the `errors[]` contract already declared. ([#24](https://github.com/cyanheads/usgs-water-mcp-server/issues/24))
- **`water_dataframe_query`'s non-SELECT and multi-statement rejections no longer echo internal canvas wording** — a mutation statement previously surfaced the canvas engine's own message ("Mutations must use registerTable, drop, or clear"), naming methods no MCP caller can invoke; both rejections now state the tool's actual read-only, single-SELECT-per-call contract. Rejections that already name the offending column or function (syntax errors, disallowed table functions) keep the engine's own message unchanged — that detail is directly actionable. ([#25](https://github.com/cyanheads/usgs-water-mcp-server/issues/25))

## Removed

- **`site_not_found` dropped from `water_get_series`'s `errors[]` contract** — no code path threw it; NWIS returns the same empty response for an unknown site and for a valid site with no data in the requested range, so the condition it described was already covered by `no_data_for_range`. ([#26](https://github.com/cyanheads/usgs-water-mcp-server/issues/26))

## Fixed

- **`water_dataframe_query` silently dropped the canvas `truncated` flag** — a query matching more than the 10,000-row cap returned the same shape as a complete result (`row_count` equals the cap either way), so a caller had no way to tell it read a partial result. The handler now returns `truncated` as a required output field, and `format()`'s rendered text states the truncation status in both directions. ([#23](https://github.com/cyanheads/usgs-water-mcp-server/issues/23))
