#29700 kernel, refactor: return error status on all fatal errors
| Reviewability | Reviews | Agreement | Size | |||||||
|---|---|---|---|---|---|---|---|---|---|---|
| #29700 kernel, refactor: return error status on all fatal errors | Review #25665 first | 0 | Blocked | 1,334 + 464 tests | ||||||
|
|
|
|
| ||||||
Reviewability: ReadyStalePaused Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs. Size: lines added or modified outside tests, then in tests; greener = smaller. | ||||||||||
Goal
Refactors validation and block storage functions across Bitcoin Core to return detailed error status and flush outcomes via util::Result and FlushResult rather than relying solely on AbortNode shutdowns. Touched subsystems include block writing, block index loading, coins state flushes, mempool transaction acceptance, assumeutxo snapshot activation, block connection, and chain activation. Upstream call sites throughout node initialization, RPC, and validation are updated and annotated with nodiscard attributes to enforce error checking.
Problem: Validation and block storage routines currently handle fatal errors like disk write or flush failures by calling AbortNode directly to initiate asynchronous shutdown without passing error context back to callers. This makes robust error handling in libbitcoinkernel difficult, forcing embedded library callers to register global notification callbacks rather than handling errors programmatically at the call site.
Evidence of importance:
- PR description: 'There are many validation functions that handle failures by calling AbortNode and triggering shutdowns, without returning error information to their callers. This makes error handling in libbitcoinkernel application code difficult, because the only way to handle these errors is to register for notification callbacks.'
- PR description: 'This PR is a pure refactoring that returns extra result information from functions without changing their behavior. It's a possible alternative to and subset of #29642, which adds similar return information but also makes behavior changes and exposes a FatalError type.'
Scope: This is a large, invasive refactoring of core validation and blockstorage error handling across 56 files that relies on util::Result extensions introduced in base PR #25665.
Risk of a mistake: medium (validation, other). A mistake in error propagation or result handling during block connection or chain flushing could cause unexpected validation halts or mask database errors.
Changed since the previous assessment: Rebased onto the updated base PR, added CI workarounds for compiler maybe-uninitialized false positives on Windows and previous-release jobs, and temporarily increased Git fetch depth in CI workflows.
What the assessment lacked:
- rest_of_diff
Reviewability
Ready · Review #25665 first
Stacked on #25665; the base PR's changes are included in this diff.
Waiting on (from the thread read):
- author: response to purpleKarrot's objection regarding Result-style error handling 2026-04-01
Agreement
Blocked
objection that needs a change, nobody has replied (purpleKarrot)
Thread notes: c:2454719003 records author rebases and comment updates; no new claims were introduced and claim statuses remain unchanged.
Objections, suggestions, and questions:
| Reviewer | Type | Harm, request, or question | Status | Must be | Author replied | Quote |
|---|---|---|---|---|---|---|
| maflcko (member) | objection, interface | Call sites may easily forget to unwrap the inner result and miss interruption | answered · author replied that replacing with Result<void, InterruptResult> would be fine and safer, though not yet changed | answered | yes | 2024-07-26: 'Seems fragile to use `util::Result<InterruptResult>`. Wrapping one result into another is fragile, because call-sites may easily forget to unwrap the inner result' Status from: 2024-08-07: ryanofsky: 'It sounds like you want `Result<InterruptResult, void>` to be replaced with `Result<void, InterruptResult>` which would ' |
| purpleKarrot (member) | objection, approach | Result-style error handling undermines runtime performance and runs contrary to C++ idioms | open | changed | no | 2026-04-01: 'I see Result-style error handling as a rustism that should be kept out of the C++ codebase of Bitcoin core.' |
| optout21 (contributor) | objection, correctness | Ignoring the return value from FlushStateToDisk while allowing it to mutate validation state creates inconsistencies | accepted · fix pushed · author clarified the comment in a push and reviewer accepted splitting the issue into #35621 | answered | yes | 2026-06-20: 'the return value from `FlushStateToDisk` is ignored, but it can cause change in `state` -- unclear if this was intended or just an unintended side effect.' Status from: 2026-06-29: optout21: 'Addressing this single case has been split off into #35621 .' |
Participants:
- Graysonbarton (none, support, 1 statements 2024-03-25 to 2024-03-25): approved without substantive rationale
- maflcko (member, objection, 1 statements 2024-07-26 to 2024-07-26): argued Result<InterruptResult> is fragile because call sites may miss interruption
- sedited (member, neutral, 1 statements 2024-10-31 to 2024-10-31): asked for a rebase
- purpleKarrot (member, objection, 1 statements 2026-04-01 to 2026-04-01): objects to util::Result error handling over runtime performance and C++ idiom concerns
- optout21 (contributor, objection, 2 statements 2026-06-20 to 2026-06-29): pointed out inconsistency with ignored FlushStateToDisk return values mutating state
Dependencies
Files
617 lines under test/bench/ci.
- src/validation.cpp +369/-193
- src/util/result.h +410/-62
- src/test/result_tests.cpp +220/-11
- src/node/blockstorage.cpp +119/-67
- src/node/chainstate.cpp +85/-53
- src/test/txpackage_tests.cpp +83/-52
- src/validation.h +44/-36
- src/kernel/result.h +67/-0
- src/util/messages.h +59/-0
- src/init.cpp +29/-24
- src/node/mempool_persist.cpp +23/-9
- src/util/messages.cpp +32/-0
- src/node/chainstate.h +6/-22
- src/kernel/bitcoinkernel.cpp +16/-11
- src/test/validation_chainstatemanager_tests.cpp +17/-10
- src/rpc/blockchain.cpp +13/-11
- src/node/blockstorage.h +13/-10
- src/test/validation_block_tests.cpp +17/-5
- src/test/validation_chainstate_tests.cpp +14/-7
- src/test/util/setup_common.cpp +13/-7
- src/rpc/mining.cpp +14/-5
- src/net_processing.cpp +9/-6
- src/test/baseindex_tests.cpp +10/-4
- src/test/chainstate_write_tests.cpp +7/-7
- src/test/fuzz/connect_block.cpp +7/-7
- src/test/fuzz/package_eval.cpp +8/-6
- src/test/fuzz/tx_pool.cpp +9/-5
- src/bench/readwriteblock.cpp +8/-5
- src/rpc/mempool.cpp +7/-4
- src/test/blockfilter_index_tests.cpp +8/-3
- src/test/blockmanager_tests.cpp +4/-4
- src/test/peerman_tests.cpp +7/-1
- test/functional/feature_assumeutxo.py +5/-3
- src/test/util/mining.cpp +5/-1
- src/node/interfaces.cpp +4/-1
- src/test/util/chainstate.h +3/-2
- src/bench/block_assemble.cpp +3/-1
- src/node/block_template_manager.cpp +3/-1
- src/node/mempool_persist.h +3/-1
- src/node/miner.cpp +2/-2
- src/node/transaction.cpp +2/-2
- src/test/fuzz/load_external_block_file.cpp +2/-2
- src/wallet/wallet.cpp +2/-2
- ci/test/00_setup_env_win64.sh +2/-1
- src/bench/load_external.cpp +2/-1
- src/test/txvalidation_tests.cpp +2/-1
- src/test/txvalidationcache_tests.cpp +2/-1
- .github/workflows/ci.yml +1/-1
- ci/test/00_setup_env_native_previous_releases.sh +1/-1
- src/test/blockchain_tests.cpp +1/-1
- src/test/fuzz/utxo_snapshot.cpp +1/-1
- src/test/fuzz/utxo_total_supply.cpp +1/-1
- src/test/interfaces_tests.cpp +1/-1
- src/test/txdownload_tests.cpp +1/-1
- src/kernel/CMakeLists.txt +1/-0
- src/util/CMakeLists.txt +1/-0
Card
The short text the ranking pass compares across PRs.
This pull request refactors validation and block storage functions that can hit fatal errors to bubble up detailed error status and flush state via util::Result and FlushResult instead of relying solely on AbortNode shutdowns. Currently, fatal failures like disk write errors trigger background shutdown callbacks without returning error context to the calling code, complicating error handling for applications consuming libbitcoinkernel. The author notes this is a pure refactor preserving node behavior designed to eliminate notification callback dependencies for library users. It depends on base PR #25665.
Data
thread read through 2026-06-29 (13 statements), head fe20fdb88e
labels: none · draft
Categories
Kernel (libbitcoinkernel)
P2 · cleanup
Enables library consumers to receive structured error information directly instead of forcing reliance on global AbortNode notification callbacks. Systematically eliminating node-specific AbortNode assumptions is a prerequisite for making validation usable as an independent library.
Membership: Explicitly targets libbitcoinkernel error reporting needs ('makes error handling in libbitcoinkernel application code difficult') and updates kernel result structures ('src/kernel/result.h', 'src/kernel/bitcoinkernel.cpp').
Factors: security/stability 1, bug 0, performance 0, user value 0, leverage 2
Utilities (logging, arguments, libraries)
P3 · cleanup (ranking pass: Moved down: a pure refactor whose payoff is kernel decoupling rather than utils-side benefit.)
Expands util::Result and associated message primitives to support detailed status codes and flush outcomes. Provides a reusable error propagation pattern for subsystems, though primary motivation is driven by kernel decoupling.
Membership: Significantly extends the shared error and result primitives in 'src/util/result.h' (+410/-62) and 'src/util/messages.h'.
Factors: security/stability 1, bug 0, performance 0, user value 0, leverage 2