Skip to content

fix: NPE when viewing the latest block header - #139

Merged
jvsena42 merged 1 commit into
mainfrom
fix/blockheader-npe-getblockheader-parsing
Jul 20, 2026
Merged

fix: NPE when viewing the latest block header#139
jvsena42 merged 1 commit into
mainfrom
fix/blockheader-npe-getblockheader-parsing

Conversation

@jvsena42

Copy link
Copy Markdown
Owner

Problem

A user reported a NullPointerException when tapping the header of the last block ("View latest block" on the Blockchain screen).

Tapping the button calls the getblockheader RPC, which Floresta answers in verbose form by default (verbosity defaults to true in floresta-node's server.rs). The verbose body is a serialized corepc_types::v29::GetBlockHeaderVerbose, whose JSON keys are merkleroot / previousblockhash and whose bits is a hex string (e.g. "1702905c").

BlockHeaderResult expected @SerializedName("merkle_root") / @SerializedName("prev_blockhash") and bits: Long. Since Gson populates non-null Kotlin fields by reflection without honoring nullability:

  • The mismatched keys left the non-null merkleRoot/prevBlockhash null, and BlockHeaderCard dereferenced them → NPE. This happens whenever bits is all digits (e.g. "170300000"), so parsing succeeds.
  • When bits contains af hex digits (the common case), Gson instead throws NumberFormatException → "Failed to parse response" snackbar.

The intermittency (crash depends on the tip block's nBits) matches a "sometimes crashes" report.

Fix

  • Map the correct JSON keys (merkleroot, previousblockhash).
  • Type bits as String.
  • Make prevBlockhash nullable (Option<String> in Floresta — genesis has none) and skip the "Previous block" row when absent.

Tests

  • GetBlockHeaderResponseParsingTest — deserializes realistic verbose getblockheader responses (hex bits, all-digit bits, and genesis with no previousblockhash) using the app's default Gson(). Fails against the old model, passes with the fix.
  • ./gradlew detekt lintDebug :app:testDebugUnitTest green.

Manual verification

Reproduced and verified on an x86_64 emulator: tapping View latest block now renders the full Block Header (Merkle Root, Previous Block, Bits, Time, Version, Nonce) with real values and no crash / no parse-error snackbar.

🤖 Generated with Claude Code

Tapping "View latest block" calls the getblockheader RPC, which Floresta
answers in verbose form by default (a serialized
corepc_types::v29::GetBlockHeaderVerbose). Its JSON keys are `merkleroot`
and `previousblockhash`, and `bits` is a hex string (e.g. "1702905c") —
not `merkle_root`/`prev_blockhash` and a Long as BlockHeaderResult
expected.

Gson populates non-null Kotlin fields by reflection without honoring
nullability, so the mismatched keys left merkleRoot/prevBlockhash null and
BlockHeaderCard dereferenced them -> NullPointerException. When `bits`
contained a-f hex digits, Gson instead threw NumberFormatException,
surfacing as a "Failed to parse response" snackbar.

Map the correct JSON keys, type `bits` as String, make prevBlockhash
nullable (genesis has none), and skip the "Previous block" row when it is
absent. Add GetBlockHeaderResponseParsingTest covering hex bits, all-digit
bits, and the genesis (no previousblockhash) case.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jvsena42
jvsena42 merged commit faaa230 into main Jul 20, 2026
2 checks passed
@jvsena42
jvsena42 deleted the fix/blockheader-npe-getblockheader-parsing branch July 20, 2026 12:55
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