---
summary: "Tighten recovery hints across BrAPI tool/resource error contracts and wire service-layer throws so declared hints actually reach the wire."
breaking: false
---

# 0.3.3 — 2026-04-29

Audit pass on every declared `recovery` field added in 0.3.2. Six hints were either restating the failure (`brapi_get_image`, `brapi_submit_observations` `observations_unsupported`, two `unknown_endpoint` variants) or actively misleading (`brapi_submit_observations` `post_unsupported` had inverted POST/PUT routing logic; `put_unsupported` suggested dropping `observationDbId` without flagging the duplicate hazard). Four more were declared on tool contracts but thrown from service code that never spread `ctx.recoveryFor`, so the hints were documentation-only — `auth_token_exchange_failed`, `auth_no_access_token`, `dataset_not_found`, `dataset_rows_missing` now carry their hints to clients.

## Changed

- **`brapi_submit_observations` recovery hints** — `observations_unsupported`, `post_unsupported`, `put_unsupported` rewritten to point at `brapi_server_info` for capability discovery, and to warn that dropping `observationDbId` to bypass `put_unsupported` would create duplicates rather than update existing rows.
- **`brapi_get_image` `images_unsupported`** rewritten from a restate-the-problem hint to a concrete recovery: run `brapi_server_info` or reconnect under a different alias.
- **`brapi_describe_filters` and `brapi://filters/{endpoint}` `unknown_endpoint`** hints now name the supported endpoints inline and reference `data.availableEndpoints` instead of the opaque "previous response" / "list field" wording.

## Fixed

- **Service-layer throws now spread `ctx.recoveryFor(reason)`** so contract hints surface on the wire. `dataset-store.ts` (`dataset_not_found`, `dataset_rows_missing`) and `server-registry.ts` (`auth_token_exchange_failed`, `auth_no_access_token`) previously declared hints on the parent tool's contract but never wired them through their `notFound()` / `forbidden()` factory throws — clients saw `data.reason` but no `data.recovery.hint`.
- **`brapi_submit_observations` `post_unsupported` hint** corrected: the prior text said "remove observationDbId so all rows route to PUT" but removing the ID actually routes a row to POST (the failing path). Now correctly advises dropping the new rows or switching servers.
