#25665 refactor: Add util::Result failure types and ability to merge result values
| Reviewability | Reviews | Agreement | Size | ||||
|---|---|---|---|---|---|---|---|
| #25665 refactor: Add util::Result failure types and ability to merge result values | Ready | 0 (+8) | Strong | 551 + 211 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
Expands util::Result to support typed failure values, multiple error and warning messages, and an update method to merge result states while preserving messages. The memory footprint of util::Result is reduced by heap-allocating failure objects. Chainstate loading and verification in init and node/chainstate are converted from custom status tuples to the updated util::Result interface.
Problem: util::Result previously could only return a success value or a single bilingual error string. Functions that need structured failure codes to differentiate error types—such as distinguishing recoverable chainstate corruption requiring a reindex from unrecoverable fatal errors—or functions returning multiple warnings and errors had to rely on out-parameters and ad-hoc tuples.
Evidence of importance:
- PR description: 'This is a key missing feature that makes the result class not useful for functions like LoadChainstate() which produce different errors that need to be handled differently.'
- PR description: 'Followup PRs #25722 and #29700 use it more broadly to return errors and warnings from wallet and kernel functions as well.'
Scope: The diff includes template metaprogramming in util/result.h and updates CMake files to add the new util/messages.cpp to bitcoin_util and bitcoinkernel libraries, alongside CI configuration workarounds for GCC maybe-uninitialized false positives.
Risk of a mistake: medium (validation, build). A mistake in chainstate load error propagation or interruption handling could cause node initialization to misclassify fatal errors or fail to trigger recovery prompts like reindexing.
Changed since the previous assessment: Added workarounds in win64 and native_previous_releases CI scripts for GCC -Wmaybe-uninitialized false positives triggered by Result member access, and fixed a clang-tidy performance-no-automatic-move warning in wallet code.
Reviewability
Ready
Nothing known that would invalidate a review now.
Waiting on (from the thread read):
- author: respond to suggestion to close and reopen in a fresh PR 2026-05-08
Agreement
Strong
substantive support, no open objection (hernanmarino, stickies-v, sedited, laanwj, achow101, sedited, arejula27, polespinasa)
Thread notes: Processed author push log updates in c:3457885805; no claims were raised or answered by the rebase notes.
Objections, suggestions, and questions:
| Reviewer | Type | Harm, request, or question | Status | Must be | Author replied | Quote |
|---|---|---|---|---|---|---|
| stickies-v (member) | objection, interface | Using Update() when not chaining can mask bugs where a fresh assignment is intended and hurts readability | fixed · fix pushed · author simplified usage in CompleteChainstateInitialization | answered | yes | 2024-04-26: 'I don't think this is good usage of Update(), since there is no chaining happening here. I would find list initialization more readable and less error-prone' Status from: 2024-07-09: ryanofsky: 'Also took suggestions to simplify usage in CompleteChainstateInitialization.' |
| maflcko (member) | objection, approach | Adding unnecessary complexity to util::Result when simpler Expected or smaller patches could be used | answered · author explained design differences between Result and Expected | answered | yes | 2024-07-04: 'My recommendation would be to keep the code as simple as possible and not add complicated features or complication that isn't required.' Status from: 2024-07-08: ryanofsky: 'I think it could be a good idea to introduce a util::Expected class if you see places in our code that need to return st' |
| hodlinator (member) | objection, approach | Conflating error return values with multi-message reporting when util::Expected should be prioritized | accepted · hodlinator acknowledged that warnings can be returned with success, departing from Expected | answered | yes | 2025-12-05: 'I think util::Result is conflating 2 related but orthogonal needs... At this point I would prefer util::Expected be merged first (#34006).' Status from: 2025-12-15: hodlinator: 'The former makes it a clearer departure from util::Expected - warnings can be added and merged into parent results while' |
| hodlinator (member) | suggestion, usefulness | Use a different example than LoadChainstate and VerifyLoadedChainstate to motivate util::Result over util::Expected | answered · author explained that LoadChainstate demonstrates error messages and status values, and documented toy examples | answered | yes | 2025-12-15: 'I maintain that the current example in this PR of applying util::Result to LoadChainstate & VerifyLoadedChainstate is not well motivated as they don't use warnings or multiple errors, and are thus a b' Status from: 2026-02-10: ryanofsky: 'Yes, your initial comment here led me to add some toy examples in the Result class documentation. I just don't see other' |
| maflcko (member) | suggestion, maintenance | Drop the commit disabling maybe-uninitialized for the native fuzz valgrind task as GCC is no longer used there | open | answered | no | 2026-04-01: 'there is no GCC anymore here, so this commit can be dropped' |
| maflcko (member) | suggestion, maintenance | Turn PR into draft or close and reopen in a fresh PR due to thread length and stale comments | answered · multiple participants agreed with reopening in a fresh PR; author has not replied yet | answered | by others | 2026-05-08: 'I think this went through many revisions in the last couple of years, and some comments do not apply anymore here. Also, with more than 300 comments, they don't load anymore on GH easily. So I think t' Status from: 2026-05-29: sedited: 'I've ACKed this pull request a few times, but I agree with the preceding comments here: This is clearly not getting revi' |
Support:
- Riahiamirreza (contributor) (ACK, 2022-08-15): Approved the pull request changes after inline code discussion [not substantive]
- hernanmarino (contributor) (Tested ACK, 2022-08-18) [both]: Tested ACK and Code review ACK
- stickies-v (member) (Concept ACK, 2022-08-19) [read]: Found the implementation high quality while acknowledging the genericness requires careful review
- sedited (member) (ACK, 2024-02-22): Re-ACK cdf7bb17563b92e48b0576a0975c168619c5aa34
- laanwj (member) (Concept ACK, 2025-10-23) [read]: Concept and code review ACK 8b892d41fdeb5756fd83f6050f27a170338d260a
- achow101 (member) (ACK, 2025-10-27): ACK 8b892d41fdeb5756fd83f6050f27a170338d260a
- sedited (member) (ACK, 2025-12-02): Re-ACK f0aff63b5ad51566e626d5b24eee08eb81df54a1
- arejula27 (contributor) (Concept ACK, 2025-12-06) [read]: Agrees with the need for error-handling workflows and merging results, particularly for high-level operations
- polespinasa (member) (Concept ACK, 2026-05-11) [read]: Useful for cleaning wallet code and for new interface methods with complex results
Participants:
- maflcko (member, objection, 43 statements 2022-07-21 to 2026-05-08): recommended simpler approaches or using Expected instead of adding complexity to Result; suggested closing and reopening a fresh PR
- stickies-v (member, support, 34 statements 2022-08-11 to 2024-04-27): Concept ACK; raised concern about Update() usage in non-chaining contexts which was resolved
- Riahiamirreza (contributor, support, 4 statements 2022-08-13 to 2022-08-15): reviewed and approved the implementation
- dongcarl (contributor, neutral, 1 statements 2022-08-16 to 2022-08-16): suggested enum naming changes for chainstate load errors
- AryanJ-NYC (none, neutral, 1 statements 2022-08-17 to 2022-08-17): pointed out an outdated comment
- hernanmarino (contributor, support, 6 statements 2022-08-17 to 2024-02-05): Tested ACK and code review ACK
- sipa (member, neutral, 1 statements 2022-08-17 to 2022-08-17): suggested making operator bool explicit
- pablomartin4btc (member, neutral, 1 statements 2022-08-19 to 2022-08-19): reported compiler warnings on GCC 9.4.0
- w0xlt (contributor, neutral, 2 statements 2022-08-30 to 2022-08-30): commented in earlier discussion
- hebasto (member, neutral, 3 statements 2023-02-12 to 2023-02-12): commented in earlier discussion
- sedited (member, support, 24 statements 2023-06-19 to 2026-05-29): multiple re-ACKs; noted review fatigue and suggested restarting in a fresh PR
- jonatack (member, neutral, 17 statements 2023-07-21 to 2023-08-07): commented in earlier discussion
- achow101 (member, support, 3 statements 2023-08-29 to 2025-10-27): code review ACK
- laanwj (member, support, 3 statements 2025-10-23 to 2025-10-23): concept and code review ACK
- hodlinator (member, objection, 14 statements 2025-12-05 to 2026-02-10): argued LoadChainstate does not motivate the extra complexity of Result over Expected
- arejula27 (contributor, support, 5 statements 2025-12-06 to 2025-12-13): Concept ACK, explored whether Expected could be extended with reporting capabilities
- polespinasa (member, support, 1 statements 2026-05-11 to 2026-05-11): Concept ACK, noting usefulness for wallet and interface methods; favored reopening in a fresh PR
Dependencies
Files
228 lines under test/bench/ci.
- src/util/result.h +371/-63
- src/test/result_tests.cpp +204/-11
- src/node/chainstate.cpp +56/-39
- src/util/messages.h +52/-0
- src/init.cpp +23/-20
- src/util/messages.cpp +32/-0
- src/node/chainstate.h +6/-22
- src/kernel/bitcoinkernel.cpp +7/-7
- src/test/util/setup_common.cpp +4/-4
- src/wallet/wallet.cpp +2/-2
- ci/test/00_setup_env_win64.sh +2/-1
- ci/test/00_setup_env_native_previous_releases.sh +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 expands the util::Result template class to support structured failure types, multiple error and warning messages, and an update method to merge sequential results. Previously, util::Result was restricted to single bilingual error strings without structured failure data, preventing its use in functions like LoadChainstate that require callers to distinguish between fatal and recoverable error conditions. It demonstrates the utility by converting chainstate loading and verification routines from ad-hoc tuples to util::Result and shrinks the memory footprint of util::Result by heap-allocating failure states. Open PRs #25722 and #29700 build on this to standardize wallet loading and kernel error reporting.
Data
thread read through 2026-05-29 (305 statements), head 2352cebe57
labels: Refactoring
Categories
Utilities (logging, arguments, libraries)
P2 · unblocks #25722 (ranking pass: Base of the util::Result chain (#26022, #25722, #29700) but placed after the three P1 safety fixes and the settings foundations.)
The PR expands util::Result to support typed failure values and merged result states, addressing a key limitation that previously forced functions to rely on ad-hoc tuples and out-parameters. It provides shared error-handling infrastructure that simplifies call sites and directly unblocks downstream refactoring in the kernel and wallet (#25722, #29700).
Membership: Significantly redesigns src/util/result.h and adds src/util/messages.h to provide typed errors and multi-message support.
Factors: security/stability 0, bug 0, performance 0, user value 0, leverage 2