Skip to content

fix(ogc): report the service's own 403 reason, and name the URL - #374

Merged
thodson-usgs merged 1 commit into
DOI-USGS:mainfrom
thodson-usgs:fix/ogc-error-messages
Aug 14, 2026
Merged

fix(ogc): report the service's own 403 reason, and name the URL#374
thodson-usgs merged 1 commit into
DOI-USGS:mainfrom
thodson-usgs:fix/ogc-error-messages

Conversation

@thodson-usgs

Copy link
Copy Markdown
Collaborator

Two user-facing defects in the OGC error message

1. A 403 was a canned guess that never read the body

was:  403: Query request denied. Possible reasons include query exceeding server limits.
now:  403: Forbidden. API key revoked. (URL: .../items?parameter_code=00060)

The 403 branch returned fixed text and explicitly did not consult the response — its docstring said so. But a missing, expired, or revoked API_USGS_PAT is the most common real 403 against api.waterdata.usgs.gov, and that user was told to go shrink their query while the service's own "API key revoked" was discarded. The legacy _querying path would have surfaced it.

It now renders the JSON envelope like every other status, and when there is no envelope to quote, names both plausible causes instead of only the rarer one.

2. No OGC error message named the URL

The legacy path appends (URL: ...); this one never did, and nothing downstream restores it — FanOutInterrupted builds its Cause: line from this same string. So a 32-chunk fan-out that died on one bad parameter_code raised a message with no indication of which chunk, which sites, or which values were in flight.

Reading the URL is guarded: httpx raises on .url for a hand-built response, and an error path must not fail while reporting a failure.

The JSON-envelope read is factored into one helper so the 403 branch and the generic path cannot drift apart again.

Not addressed here

_querying._raise_for_status and ogc.errors._raise_for_non_200 remain two implementations of one contract, and each is still missing the other's improvement — the 414 "split your query" remediation exists only on the legacy side. Unifying them means moving the message builder down to a layer ogc is permitted to import (.importlinter forbids ogc -> _querying), which is a structural change rather than a bug fix and deserves its own review.

Testing

  • Four new regression tests: the 403 envelope reaches the user; a bodiless 403 names the credential cause; messages carry the URL; and a response with no request attached still raises cleanly rather than blowing up inside the error path.
  • 791 passed; mypy --strict, ruff, xenon, complexipy, lint-imports all pass.

Found by the scan in #372, split out because it changes user-visible behavior. Independent of #372 and #373 — branches off main.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BTaSm7HmVb94RSJiKW4WAS

A 403 returned fixed text naming only "query exceeding server limits"
and never read the body, so a missing, expired, or revoked API_USGS_PAT
-- the most common real 403 against api.waterdata.usgs.gov -- was
reported as a query-size problem while the service's own "API key
revoked" was discarded. 403 now shares the generic path: the JSON error
body when there is one (a USGS code/description envelope or a gateway
message, flat or nested under "error"), the text snippet otherwise, and
credential guidance only when there is no body to quote.

No OGC error message named the URL. The legacy path appends it, this one
never did, and nothing downstream restores it -- FanOutInterrupted builds
its "Cause:" line from this same string -- so a fan-out that died on one
bad chunk gave no indication of which request was in flight. Reading the
URL is guarded: httpx raises on `.url` for a hand-built response, and an
error path must not fail while reporting a failure.

Not addressed here: _querying._raise_for_status and
ogc.errors._raise_for_non_200 remain two implementations of one contract,
and the 414 "split your query" remediation is still only on the legacy
side. Unifying them means moving the message builder to a layer `ogc` may
import (.importlinter forbids ogc -> _querying) -- a structural change
rather than a bug fix.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BTaSm7HmVb94RSJiKW4WAS
@thodson-usgs
thodson-usgs marked this pull request as ready for review August 14, 2026 15:16
@thodson-usgs
thodson-usgs force-pushed the fix/ogc-error-messages branch from 036d6ea to 765b374 Compare August 14, 2026 15:21
@thodson-usgs
thodson-usgs merged commit b5d0105 into DOI-USGS:main Aug 14, 2026
10 checks passed
@thodson-usgs
thodson-usgs deleted the fix/ogc-error-messages branch August 14, 2026 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant