cli: Display warning arrays in -getinfo #36212

pull LittleYier wants to merge 2 commits into bitcoin:master from LittleYier:cli-fix-getinfo-warnings changing 2 files +15 −6
  1. LittleYier commented at 10:55 PM on September 9, 2026: contributor

    -getinfo swallowed warnings when getnetworkinfo returns an array instead of string, showing (none) even with active prerelease warnings on regtest.

    Just join array items with newline and keep the fallback for legacy strings / empty cases. Threw together a quick test to cover it.

    Tested on m1 mac, regtest warning shows up fine now and py tests pass.

  2. cli: Display warning arrays in -getinfo
    Render all warnings returned by getnetworkinfo, separated by newlines. Preserve legacy string responses and the empty-warning fallback.
    045bb80f3d
  3. LittleYier requested review from Copilot on Sep 9, 2026
  4. DrahtBot added the label Scripts and tools on Sep 9, 2026
  5. DrahtBot commented at 10:55 PM on September 9, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/36212.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline and AI policy for information on the review process.

    Type Reviewers
    Concept ACK stickies-v

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  6. ?
    copilot_work_started LittleYier
  7. Copilot commented at 10:58 PM on September 9, 2026: none

    🟢 Approval recommended

    All reviewed changes are covered and no blocking issues remain.

    <details> <summary>Pull request overview</summary>

    Updates bitcoin-cli -getinfo to display warning arrays while retaining legacy string handling.

    Changes:

    • Joins warning arrays with newlines.
    • Preserves (none) fallback behavior.
    • Adds coverage for array, string, and versionbits warnings.

      </details>

    <details> <summary>File summaries</summary>

    File Description
    test/functional/interface_bitcoin_cli.py Tests array and legacy warning formats.
    test/functional/feature_versionbits_warning.py Verifies active warnings appear in -getinfo.
    src/bitcoin-cli.cpp Formats warning arrays and legacy strings.

    </details>

    <details> <summary>Review details</summary>

    • Files reviewed: 3/3 changed files
    • Comments generated: 0
    • Review effort level: Lite

      </details>


    💡 <a href="/bitcoin/bitcoin/new/master?filename=.github/skills/code-review/SKILL.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add a code-review agent skill</a> or configure MCP servers for context-aware, tailored reviews. <a href="https://docs.github.com/copilot/how-tos/use-copilot-agents/request-a-code-review/use-code-review?tool=webui#mcp-servers-and-agent-skills" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn more in the docs.</a>

  8. sedited requested review from stickies-v on Sep 10, 2026
  9. in test/functional/interface_bitcoin_cli.py:243 in 045bb80f3d
     238 | @@ -239,6 +239,13 @@ def run_test(self):
     239 |          assert_equal(cli_get_info['Proxies'], network_info['networks'][0]['proxy'])
     240 |          assert_equal(Decimal(cli_get_info['Difficulty']), blockchain_info['difficulty'])
     241 |          assert_equal(cli_get_info['Chain'], blockchain_info['chain'])
     242 | +        expected_warnings = "\n".join(network_info['warnings']) or "(none)"
     243 | +        assert cli_get_info_string.endswith(f"Warnings: {expected_warnings}")
    


    stickies-v commented at 10:36 AM on September 10, 2026:

    Would it be better to update cli_get_info_string_to_dict to properly parse Warnings, like we already do for Balances?

  10. in test/functional/interface_bitcoin_cli.py:245 in 045bb80f3d
     238 | @@ -239,6 +239,13 @@ def run_test(self):
     239 |          assert_equal(cli_get_info['Proxies'], network_info['networks'][0]['proxy'])
     240 |          assert_equal(Decimal(cli_get_info['Difficulty']), blockchain_info['difficulty'])
     241 |          assert_equal(cli_get_info['Chain'], blockchain_info['chain'])
     242 | +        expected_warnings = "\n".join(network_info['warnings']) or "(none)"
     243 | +        assert cli_get_info_string.endswith(f"Warnings: {expected_warnings}")
     244 | +
     245 | +        self.log.info("Test -getinfo with deprecated string warnings")
    


    stickies-v commented at 10:59 AM on September 10, 2026:

    This doesn't seem all that relevant to testing the cli, makes sense to drop I think?

  11. in test/functional/feature_versionbits_warning.py:117 in 045bb80f3d
     113 | @@ -114,6 +114,9 @@ def run_test(self):
     114 |          # Check that get*info() shows the versionbits unknown rules warning
     115 |          assert WARN_UNKNOWN_RULES_ACTIVE in ",".join(node.getmininginfo()["warnings"])
     116 |          assert WARN_UNKNOWN_RULES_ACTIVE in ",".join(node.getnetworkinfo()["warnings"])
     117 | +        if self.is_cli_compiled():
    


    stickies-v commented at 11:13 AM on September 10, 2026:

    I don't think testing the cli is relevant in this versionbits warning test?

  12. stickies-v commented at 11:16 AM on September 10, 2026: contributor

    Concept ACK, thanks for catching this

  13. test: Parse getinfo warnings in CLI helper
    Parse the complete final Warnings section after removing ANSI codes, preserving multiline messages and colons. Compare warnings through the existing dictionary helper.
    
    Keep CLI coverage in the CLI test by dropping the separate deprecated-mode restart and the CLI assertion in the versionbits test.
    59d0d24d6c
  14. LittleYier commented at 1:31 PM on September 12, 2026: contributor

    Pushed in 59d0d24 1.Tweaked the helper to grab the whole warnings section so colons and newlines don't get chopped. 2. Dropped the extra restart + cli check in versionbits test as suggested. Thanks for the quick review!

  15. in test/functional/interface_bitcoin_cli.py:47 in 59d0d24d6c
      41 | @@ -42,13 +42,17 @@
      42 |  def cli_get_info_string_to_dict(cli_get_info_string):
      43 |      """Helper method to convert human-readable -getinfo into a dictionary"""
      44 |      cli_get_info = {}
      45 | -    lines = cli_get_info_string.splitlines()
      46 | -    line_idx = 0
      47 | +    # Remove ansi colour codes
      48 |      ansi_escape = re.compile(r'(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]')
      49 | +    lines = ansi_escape.sub('', cli_get_info_string).splitlines()
    


    stickies-v commented at 12:09 PM on September 16, 2026:

    I don't think this code that deals with line processing / escaping needs to be touched for the change you're trying to make? Would prefer keeping that part as-is, and just keep the changes from L51 onwards.

  16. in src/bitcoin-cli.cpp:1520 in 59d0d24d6c
    1515 | @@ -1516,7 +1516,10 @@ static void ParseGetInfoResult(UniValue& result)
    1516 |          result_string += "\n";
    1517 |      }
    1518 |  
    1519 | -    const std::string warnings{result["warnings"].getValStr()};
    1520 | +    const UniValue& warnings_value{result["warnings"]};
    1521 | +    const std::string warnings{warnings_value.isArray()
    


    stickies-v commented at 12:43 PM on September 16, 2026:

    would be helpful to add a docstring here like:

    warnings is returned as a string when -deprecatedrpc=warnings is set

    so it's more obvious this should be removed when the deprecatedrpc option is removed too

  17. in src/bitcoin-cli.cpp:1522 in 59d0d24d6c
    1515 | @@ -1516,7 +1516,10 @@ static void ParseGetInfoResult(UniValue& result)
    1516 |          result_string += "\n";
    1517 |      }
    1518 |  
    1519 | -    const std::string warnings{result["warnings"].getValStr()};
    1520 | +    const UniValue& warnings_value{result["warnings"]};
    1521 | +    const std::string warnings{warnings_value.isArray()
    1522 | +        ? Join(warnings_value.getValues(), "\n", [](const UniValue& warning) { return warning.get_str(); })
    1523 | +        : warnings_value.getValStr()};
    


    stickies-v commented at 12:43 PM on September 16, 2026:

    nit: if the original code had used get_str() with type checking, this issue probably wouldn't have stayed under the radar.

            : warnings_value.get_str()};
    

    stickies-v commented at 1:29 PM on September 16, 2026:

    I'm okay with the current approach too, but perhaps it would be more consistent to follow the layout of the Balances section, which is to make a dedicated Warnings header and then print each item underneath it, as opposed the first one next to it and the next one(s) underneath it? And then when the -deprecatedrpc=warnings option is removed in the future, no warnings will just not print anything in the output, which I think is nicer than "Warnings: (none)".

    <details> <summary>git diff on 59d0d24d6c</summary>

    diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
    index 1ee3c03431..865dd3e9c3 100644
    --- a/src/bitcoin-cli.cpp
    +++ b/src/bitcoin-cli.cpp
    @@ -1517,10 +1517,12 @@ static void ParseGetInfoResult(UniValue& result)
         }
     
         const UniValue& warnings_value{result["warnings"]};
    -    const std::string warnings{warnings_value.isArray()
    -        ? Join(warnings_value.getValues(), "\n", [](const UniValue& warning) { return warning.get_str(); })
    -        : warnings_value.getValStr()};
    -    result_string += strprintf("%sWarnings:%s %s", YELLOW, RESET, warnings.empty() ? "(none)" : warnings);
    +    if (warnings_value.isArray() && !warnings_value.empty()) {
    +        result_string += strprintf("%sWarnings%s\n%s", YELLOW, RESET, Join(warnings_value.getValues(), "\n", [](const UniValue& warning) { return warning.get_str(); }));
    +    } else {
    +        const std::string warnings{warnings_value.getValStr()};
    +        result_string += strprintf("%sWarnings:%s %s", YELLOW, RESET, warnings.empty() ? "(none)" : warnings);
    +    }
     
         result.setStr(result_string);
     }
    diff --git a/test/functional/interface_bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py
    index 47e9bdd4bd..cf07eec3fe 100755
    --- a/test/functional/interface_bitcoin_cli.py
    +++ b/test/functional/interface_bitcoin_cli.py
    @@ -48,10 +48,12 @@ def cli_get_info_string_to_dict(cli_get_info_string):
         line_idx = 0
         while line_idx < len(lines):
             line = lines[line_idx]
    -        if line.startswith("Warnings: "):
    -            # Warnings is the final section and can span multiple lines.
    -            cli_get_info["Warnings"] = "\n".join(lines[line_idx:]).removeprefix("Warnings: ")
    -            break
    +        if line == "Warnings":
    +            # When "Warnings" is a header line, all of the following lines contain one warning until an empty line
    +            cli_get_info["Warnings"] = []
    +            while line_idx + 1 < len(lines) and lines[line_idx + 1] != '':
    +                line_idx += 1
    +                cli_get_info["Warnings"].append(lines[line_idx])
             elif "Balances" in line:
                 # When "Balances" appears in a line, all of the following lines contain "balance: wallet" until an empty line
                 cli_get_info["Balances"] = {}
    @@ -243,8 +245,7 @@ class TestBitcoinCli(BitcoinTestFramework):
             assert_equal(cli_get_info['Proxies'], network_info['networks'][0]['proxy'])
             assert_equal(Decimal(cli_get_info['Difficulty']), blockchain_info['difficulty'])
             assert_equal(cli_get_info['Chain'], blockchain_info['chain'])
    -        expected_warnings = "\n".join(network_info['warnings']) or "(none)"
    -        assert_equal(cli_get_info['Warnings'], expected_warnings)
    +        assert_equal(cli_get_info['Warnings'], network_info['warnings'] or "(none)")
     
             self.log.info("Test -getinfo and bitcoin-cli return all proxies")
             self.restart_node(0, extra_args=["-proxy=127.0.0.1:9050", "-i2psam=127.0.0.1:7656"])
    
    

    </details>

  18. stickies-v commented at 2:24 PM on September 16, 2026: contributor

    Can you please squash the 2 commits?


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-10-11 16:51 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me