Skip to content

fix(transport): reject 200-OK { type: "error" } envelopes with HttpRequestError - #94

Merged
joeblau merged 1 commit into
mainfrom
fix/issue-91
Aug 4, 2026
Merged

fix(transport): reject 200-OK { type: "error" } envelopes with HttpRequestError#94
joeblau merged 1 commit into
mainfrom
fix/issue-91

Conversation

@joeblau

@joeblau joeblau commented Aug 4, 2026

Copy link
Copy Markdown

Summary

  • HttpTransport.request() now throws HttpRequestError when a 200-OK body is Hyperliquid's top-level { type: "error", message } failure envelope, carrying the server's own message (restores the check upstream @nktkas/hyperliquid had)
  • Only the top level matches: arrays, nested type: "error" fields, and exchange-style { status: "err" } envelopes still resolve
  • The invalid-JSON try block was narrowed to the parse alone so the new throw isn't rewrapped
  • Explorer API layer's assertSuccessResponse documented as the safety net for custom transports; docs/error-handling.md updated; 6 new transport tests

Verification (3-agent agreement)

  • Claude (Opus/Fable, this session): APPROVE after line-by-line review
  • Kimi K3 Max: APPROVE ("Tests: meaningful and cover exactly the issue's matrix... No material defects")
  • Codex gpt-5.6-sol @ xhigh: APPROVE ("No material defects found")
  • Integration: all four fix branches merged together pass bun run check + 1965 offline tests, 0 fail

Fixes #91

🤖 Generated with Claude Code

…questError

Hyperliquid reports some failures inside a 200 OK response as a
top-level { type: "error", message } envelope (the explorer/rpc failure
shape). HttpTransport.request() validated only the HTTP status and
Content-Type, so such envelopes were returned to callers as data:
unvalidated info methods silently yielded the envelope as a "result",
and schema-validated methods failed with a confusing ValidationError
instead of the server's message. Upstream @nktkas/hyperliquid threw on
these envelopes; this fork had dropped the check.

request() now checks the parsed body after JSON.parse: a non-null,
non-array object with type === "error" throws HttpRequestError carrying
the server's message string when present (truncated body text
otherwise), a readable recreated Response, and the redacted request
snapshot. The invalid-JSON try block is narrowed to the parse alone so
the new throw is not rewrapped as "Invalid JSON response body".

Only top-level type === "error" envelopes throw: array bodies, normal
objects, nested type fields, and the exchange endpoint's
{ status: "err" } envelope (owned by the API layer) still resolve at
transport level. The explorer API layer's assertSuccessResponse remains
as a safety net for custom transports and is documented as such.

Docs: module diagram, class/method JSDoc, and error-handling.md updated
to enumerate the new failure case.

Fixes #91

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@joeblau
joeblau merged commit 1882a6b into main Aug 4, 2026
6 checks passed
@joeblau joeblau mentioned this pull request Aug 4, 2026
joeblau added a commit that referenced this pull request Aug 4, 2026
Four fixes, each cross-verified to agreement by three independent
reviewers (Claude, Kimi K3 Max, Codex gpt-5.6-sol xhigh):

- #89 subscription failures notify every subscriber + failureSignal (#93)
- #90 WebSocket message pacing on by default, flush charging fixed (#96)
- #91 200-OK { type: "error" } envelopes throw HttpRequestError (#94)
- #92 wallet shape detection by member presence, not arity (#95)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@joeblau
joeblau deleted the fix/issue-91 branch August 4, 2026 05:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

HttpTransport no longer detects 200-OK {type:"error"} envelopes

1 participant