Fix unguarded /outspends response parsing in MempoolSpaceIndexerApi - #973
Merged
Merged
Conversation
FetchUtxoAsync and GetIsSpentOutputsOnTransactionAsync called the indexer's /outspends endpoint and immediately deserialized the response as JSON without checking IsSuccessStatusCode first, unlike every other call site in this file. When the indexer returns a plain-text error body (e.g. "Internal Server Error" under load), this crashed with a confusing System.Text.Json.JsonException: 'I' is an invalid start of a value, instead of a clear indexer error. Discovered via SendFundsTest UAT failures where SendAmount failed with this exact JsonException while test.indexer.angor.io was under load. After the fix, the same failure now surfaces as: "Indexer test.indexer.angor.io returned an error: Internal Server Error" — matching the existing error-handling pattern used everywhere else in the file. This doesn't fix indexer instability under load, but ensures failures are diagnosable instead of masked by an unrelated parse exception.
This was referenced Sep 23, 2026
dangershony
added a commit
that referenced
this pull request
Sep 24, 2026
#975) Found while re-running the full UAT suite after merging #973/#974: SendFundsTest.ThreeUsersSendToEachOther reproducibly failed (2/2 runs) at the final sweep-all verification with: Expected sweptA to be less than 4.0 because A receives C's balance minus the network fee (fee is subtracted from the swept amount), but found 4.0. Root cause: FundsViewModel.TotalBalance formats the displayed balance with "F4" (4 decimal places). At the 2 sat/vB fee rate used by this test, a single-input sweep transaction costs roughly 200-300 sats (~0.000002-0.000003 BTC) — three orders of magnitude below what F4 can represent. The fee is genuinely subtracted on-chain; it just rounds away completely at this display precision, so the strict BeLessThan assertion was never reliable at this fee rate. This wasn't caught before because earlier runs failed on unrelated indexer/faucet issues before ever reaching this check; now that #973/#974 fixed those, the test reaches this point reliably and exposed the latent assertion bug. Fix: relax to BeLessThanOrEqualTo, since "fee not visible at 4-decimal display precision" is expected, correct behavior, not a bug. Verified: re-ran SendFundsTest after the fix — passes reliably.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
FetchUtxoAsyncandGetIsSpentOutputsOnTransactionAsyncinMempoolSpaceIndexerApi.cscalled the indexer's/outspendsendpoint and immediately deserialized the response as JSON without checkingIsSuccessStatusCodefirst — unlike every other call site in this file, which all guard with the standard pattern:When the indexer returns a plain-text error body (e.g.
Internal Server Error) instead of JSON — which happens under load — this crashed with a confusing:...instead of a clear, actionable indexer error.
How this was found
While chasing an intermittent UAT failure in
SendFundsTest(three wallets sending funds to each other in rounds against the Angornet test indexer),SendAmountfailed with the JSON parse exception above whiletest.indexer.angor.iowas under load.Fix
Added the same
IsSuccessStatusCodeguard (and_networkService.CheckAndHandleError) before deserializing in both call sites, matching the existing pattern used everywhere else in this file.After the fix, the same underlying indexer issue now surfaces as a clear, diagnosable error instead of a crash:
This doesn't fix indexer instability under load (that's a separate, ongoing infra concern — see #971), but it ensures failures are always surfaced with a meaningful message instead of being masked by an unrelated JSON parse exception.
Testing
dotnet test src/shared/Angor.Shared.Tests/Angor.Shared.Tests.csproj— 160/160 passed.App.Test.Uat/SendFundsTestbefore/after: confirmed the JSON crash is gone and replaced with the clear indexer error message. The test itself still intermittently fails due to indexer load, tracked separately.