Skip to content

chore(deps): bump ibex-client to ^3.3.0 for structured error details - #477

Merged
islandbitcoin merged 4 commits into
mainfrom
chore/bump-ibex-client-330
Aug 12, 2026
Merged

chore(deps): bump ibex-client to ^3.3.0 for structured error details#477
islandbitcoin merged 4 commits into
mainfrom
chore/bump-ibex-client-330

Conversation

@islandbitcoin

Copy link
Copy Markdown
Contributor

Summary

Bumps ibex-client ^3.2.0 → ^3.3.0 (v3.3.0 release, lnflash/ibex-client#12).

3.3.0's ApiError populates httpCode, ibexResponse, and ibexMessage at construction, so every IBEX call site now surfaces the response detail — #476 could only extract it at the payInvoice raw-fetch seam under pinned 3.2.0, and errorHandler already duck-types ibexMessage, so no code changes are needed beyond the bump.

Tests

New ibex-client 3.3.0 integration block in errors.spec.ts constructs the real ApiError (no Object.assign simulation) and pins:

  • constructor extraction (httpCode/ibexResponse/ibexMessage)
  • insufficient-balance classification with internal account-UUID stripping
  • unclassified fall-through carrying the detail onto the generic IbexError

test:unit ibex suites: 7 suites / 72 tests green; tsc-check and eslint clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_015fAxSGEsL2LsMx1uCjAzHH

ibex-client 3.3.0 (lnflash/ibex-client#12) populates httpCode,
ibexResponse, and ibexMessage on ApiError at construction, so every
IBEX call site now gets the response detail #476 could only extract
at the payInvoice raw-fetch seam under pinned 3.2.0.

No code changes needed: errors.ts already duck-types ibexMessage.
New integration tests construct the real 3.3.0 ApiError (no simulated
fields) and pin extraction, insufficient-balance classification with
account-id stripping, and the unclassified fall-through detail.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015fAxSGEsL2LsMx1uCjAzHH
bobodread876 and others added 3 commits August 12, 2026 08:19
Review fixes for #477:

- errorHandler/httpErrorHandler no longer prepend the IBEX body detail
  when the message already contains it — ibex-client@3.3.0's ApiError
  embeds "IBEX response (<code>): <detail>" itself, so the unclassified
  carries were logging every unrecognized IBEX error's detail twice
  (and the duplicate reached Discord alert embeds via #475). Tests
  extended to pin the detail appearing exactly once (verified failing
  against the pre-fix code).
- Rewrote the payInvoice raw-fetch seam comment: the 3.2.0
  body-discarding rationale no longer holds on 3.3.0; the seam is
  belt-and-braces only, follow-up to collapse it filed as #478.
- Rewrote httpErrorHandler's docblock and errorHandler's classification
  comment to describe 3.3.0 behavior (ApiError carries the body;
  httpErrorHandler stays as defense-in-depth for the raw-fetch seam).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015fAxSGEsL2LsMx1uCjAzHH
httpErrorHandler extracted the detail from the raw FetchError's .data
(uncapped) but compared it against the ApiError-wrapped message, which
embeds only ibex-client's MAX_IBEX_MESSAGE_LENGTH-truncated copy. For
any body over the cap — the Cloudflare-HTML-error-page outage the cap
exists for — the includes() guard always missed, prepending the full
multi-KB body onto every failing call's message with the first 500
chars duplicated (truncated + full), defeating the upstream cap in
logs and Discord alert embeds.

Construct the ApiError first and derive the detail from it: both sides
of the dedupe comparison now use the same bounded string. When the raw
error is already an IbexClientError, wrapped === raw and the extraction
is unchanged. The uncapped body remains available on ibexResponse.

Adds a regression test feeding a body 4x over MAX_IBEX_MESSAGE_LENGTH
through httpErrorHandler, asserting the message stays bounded and the
truncated detail appears exactly once (fails against the previous
implementation).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015fAxSGEsL2LsMx1uCjAzHH
…survive onto the returned error

Round-3 review fix for PR #477: the comment claimed the uncapped body
stays reachable on wrapped.ibexResponse, but wrapped is function-local
and IbexError's constructor copies only name/httpCode/message — during
a Cloudflare-outage scenario a maintainer would search for ibexResponse
and find nothing. State reality: the uncapped body is deliberately
dropped so pino never serializes a multi-KB blob.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015fAxSGEsL2LsMx1uCjAzHH
@islandbitcoin
islandbitcoin merged commit 75863c6 into main Aug 12, 2026
15 checks passed
islandbitcoin added a commit that referenced this pull request Aug 13, 2026
…479)

payInvoice called the generated SDK through Ibex.authentication.withAuth
directly so a failed payment's FetchError — carrying the parsed IBEX error
body on `.data` — reached httpErrorHandler intact. The seam existed because
ibex-client 3.2.0's ApiError discarded the response body
(lnflash/ibex-client#6), which made insufficient-balance 400s
unclassifiable through the standard path.

As of ibex-client 3.3.0 (#477), ApiError extracts the body itself
(httpCode / ibexResponse / ibexMessage) and errorHandler classifies it
through the standard path, so payInvoice now uses the same
`Ibex.payInvoiceV2(body).then(errorHandler)` shape as every sibling method.

httpErrorHandler had no remaining callers after the collapse and is removed
along with its dedicated tests; every behavioral pin it carried
(insufficient-balance classification with UUID-stripped client message and
preserved detail, single-copy detail on unclassified errors, capped
message on oversized bodies, status preservation, network-failure and
non-Error tolerance) now lives on the errorHandler path in errors.spec.ts,
constructed as real ApiErrors — the exact shape the collapsed path
produces. pay-invoice.spec.ts mocks ibex-client 3.3.0's wrapper contract
and gains a payInvoice-level auth-failure test pinning ErrorLevel.Critical.

Fixes #478


Claude-Session: https://claude.ai/code/session_015fAxSGEsL2LsMx1uCjAzHH

Co-authored-by: Dread <bobodread@bobodread.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.

2 participants