fix(controller): guard against nil account in UpdateTelemetry - #535
Open
erhnysr wants to merge 3 commits into
Open
fix(controller): guard against nil account in UpdateTelemetry#535erhnysr wants to merge 3 commits into
erhnysr wants to merge 3 commits into
Conversation
…count Add a regression test that drives UpdateTelemetry() with a state machine whose store Get() always fails, forcing GetAccount() to return a nil account with an error. The test asserts UpdateTelemetry() does not panic; it fails on the current code because the account metric branch dereferences the nil account.
UpdateTelemetry() dropped the error from GetAccount() and dereferenced the returned account directly. GetAccount() returns a nil account together with an error on a store read or unmarshal failure, so the account metric branch could panic with a nil pointer dereference. Add a nil check before reading the account amount, matching the validator metric branch directly above which already guards its result with 'v != nil'.
erhnysr
force-pushed
the
fix/update-telemetry-nil-account
branch
from
August 30, 2026 18:00
6b95794 to
ed2dbfd
Compare
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
UpdateTelemetry()incontroller/block.go:775drops the error fromGetAccount()and dereferences the returned account directly:GetAccount()returns a nil account together with an error on a store read or unmarshal failure (fsm/account.go:31-35):So when the store errors,
aisnilanda.Amountpanics with a nil pointer dereference.UpdateTelemetry()runs in adeferafter the block is committed, so the panic surfaces on the post-commit path.The core argument is an internal inconsistency: the validator branch immediately above already guards its result, while the account branch does not:
GetValidator()andGetAccount()share the same(nil, err)-on-failure contract, so the two branches should be guarded the same way.Fix
A single clause, matching the validator branch directly above:
Returning the error is not an option here:
UpdateTelemetry()is avoidbest-effort telemetry function, and the in-function convention is drop-the-error, guard-the-result (exactly what the validator branch does). Propagating the error would mean changing the signature and every caller for a metrics-only side effect, which is out of scope and inconsistent with the surrounding code.Tests
New test in
controller/block_test.gothat injects a store whoseGet()always fails, forcingGetAccount()to return(nil, err), then assertsUpdateTelemetry()does not panic. This follows the failing-store injection pattern from merged PR #530, with two deliberate differences:require.NotPanicsrather than fix(fsm): return LoadCommittee errors in ApplyBlock #530'srequire.ErrorContains, because this symptom is a panic, not a returned error (UpdateTelemetry()returns nothing).newTestStateMachine, which constructs aStateMachineby setting unexported fields directly (only legal inside thefsmpackage). From thecontrollerpackage I used the exportedSetStore()plus minimal reflection to allocate the unexportedcachefield — the same cross-package construction pattern thecmd/rpctests already use.Failing first — before the fix (
cdfd182)The panic stack points straight at
controller/block.go:775.Passing — after the fix (
6b95794)Full package run:
Notes
CONTRIBUTING.mdmentions updating.docs/CHANGELOG.md, but that file does not exist in the repository and recent merged PRs (e.g. #494) did not add one, so I did not fabricate a changelog entry.