{
 "number": 36212,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/36212",
 "title": "cli: Display warning arrays in -getinfo",
 "author": "LittleYier",
 "author_association": "CONTRIBUTOR",
 "created_at": "2026-09-09T22:55:51Z",
 "updated_at": "2026-09-16T14:24:17Z",
 "age_days": 7,
 "draft": false,
 "labels": [
  "Scripts and tools"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "59d0d24d6cb67a4ddfe9951846ea90db42e9ef6f",
 "head_ref": "cli-fix-getinfo-warnings",
 "head_repo": "LittleYier/bitcoin",
 "head_history": [],
 "additions": 15,
 "deletions": 6,
 "changed_files": 2,
 "commit_count": 2,
 "size_bucket": "S",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "concept_ack": [
     {
      "login": "stickies-v",
      "url": "https://github.com/bitcoin/bitcoin/pull/36212#pullrequestreview-5165999127"
     }
    ]
   },
   "conflicts": []
  }
 },
 "acks_parsed": {
  "stickies-v": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-09-10T11:16:35Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 0,
  "stale_ack": 0,
  "concept_ack": 1,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 0,
  "changes_requested": 0,
  "distinct_reviewers": [
   "stickies-v"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-09-12T13:31:53Z",
  "last_reviewer_activity": "2026-09-16T14:24:17Z",
  "last_reviewer": "stickies-v",
  "author_silent_days": 5,
  "waiting_on_author_days": 1,
  "days_since_update": 1
 },
 "refs": {
  "mentioned": [],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [],
  "conflicts": []
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/bitcoin-cli.cpp",
  "test/functional/feature_versionbits_warning.py",
  "test/functional/interface_bitcoin_cli.py"
 ],
 "body": "`-getinfo` swallowed warnings when `getnetworkinfo` returns an array instead of string, showing `(none)` even with active prerelease warnings on regtest.\n\nJust join array items with newline and keep the fallback for legacy strings / empty cases. Threw together a quick test to cover it.\n\nTested on m1 mac, regtest warning shows up fine now and py tests pass.",
 "commits": [
  {
   "sha": "045bb80f3dc1c745b445e5c6d512eabbe576cdf3",
   "date": "2026-09-09T22:49:55Z",
   "message": "cli: Display warning arrays in -getinfo\n\nRender all warnings returned by getnetworkinfo, separated by newlines. Preserve legacy string responses and the empty-warning fallback."
  },
  {
   "sha": "59d0d24d6cb67a4ddfe9951846ea90db42e9ef6f",
   "date": "2026-09-12T10:21:14Z",
   "message": "test: Parse getinfo warnings in CLI helper\n\nParse the complete final Warnings section after removing ANSI codes, preserving multiline messages and colons. Compare warnings through the existing dictionary helper.\n\nKeep CLI coverage in the CLI test by dropping the separate deprecated-mode restart and the CLI assertion in the versionbits test."
  }
 ],
 "timeline": [
  {
   "t": "2026-09-10T10:36:44Z",
   "kind": "review_comment",
   "who": "stickies-v",
   "assoc": "MEMBER",
   "path": "test/functional/interface_bitcoin_cli.py",
   "commit": "045bb80f3dc1c745b445e5c6d512eabbe576cdf3",
   "in_reply_to": null,
   "text": "Would it be better to update `cli_get_info_string_to_dict` to properly parse `Warnings`, like we already do for `Balances`?"
  },
  {
   "t": "2026-09-10T10:59:01Z",
   "kind": "review_comment",
   "who": "stickies-v",
   "assoc": "MEMBER",
   "path": "test/functional/interface_bitcoin_cli.py",
   "commit": "045bb80f3dc1c745b445e5c6d512eabbe576cdf3",
   "in_reply_to": null,
   "text": "This doesn't seem all that relevant to testing the cli, makes sense to drop I think?"
  },
  {
   "t": "2026-09-10T11:13:46Z",
   "kind": "review_comment",
   "who": "stickies-v",
   "assoc": "MEMBER",
   "path": "test/functional/feature_versionbits_warning.py",
   "commit": "045bb80f3dc1c745b445e5c6d512eabbe576cdf3",
   "in_reply_to": null,
   "text": "I don't think testing the cli is relevant in this versionbits warning test?"
  },
  {
   "t": "2026-09-10T11:16:35Z",
   "kind": "review",
   "who": "stickies-v",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "045bb80f3dc1c745b445e5c6d512eabbe576cdf3",
   "text": "Concept ACK, thanks for catching this"
  },
  {
   "t": "2026-09-12T13:31:53Z",
   "kind": "comment",
   "who": "LittleYier",
   "assoc": "CONTRIBUTOR",
   "text": "Pushed in 59d0d24\n1.Tweaked the helper to grab the whole warnings section so colons and newlines don't get chopped.\n2. Dropped the extra restart + cli check in versionbits test as suggested.\nThanks for the quick review!"
  },
  {
   "t": "2026-09-16T12:09:18Z",
   "kind": "review_comment",
   "who": "stickies-v",
   "assoc": "MEMBER",
   "path": "test/functional/interface_bitcoin_cli.py",
   "commit": "59d0d24d6cb67a4ddfe9951846ea90db42e9ef6f",
   "in_reply_to": null,
   "text": "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."
  },
  {
   "t": "2026-09-16T12:43:02Z",
   "kind": "review_comment",
   "who": "stickies-v",
   "assoc": "MEMBER",
   "path": "src/bitcoin-cli.cpp",
   "commit": "59d0d24d6cb67a4ddfe9951846ea90db42e9ef6f",
   "in_reply_to": null,
   "text": "would be helpful to add a docstring here like:\n[quoted text omitted]\n\nso it's more obvious this should be removed when the `deprecatedrpc` option is removed too"
  },
  {
   "t": "2026-09-16T12:43:52Z",
   "kind": "review_comment",
   "who": "stickies-v",
   "assoc": "MEMBER",
   "path": "src/bitcoin-cli.cpp",
   "commit": "59d0d24d6cb67a4ddfe9951846ea90db42e9ef6f",
   "in_reply_to": null,
   "text": "nit: if the original code had used `get_str()` with type checking, this issue probably wouldn't have stayed under the radar.\n```suggestion\n        : warnings_value.get_str()};\n```"
  },
  {
   "t": "2026-09-16T13:29:59Z",
   "kind": "review_comment",
   "who": "stickies-v",
   "assoc": "MEMBER",
   "path": "src/bitcoin-cli.cpp",
   "commit": "59d0d24d6cb67a4ddfe9951846ea90db42e9ef6f",
   "in_reply_to": null,
   "text": "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)\".\n\ngit diff on 59d0d24d6c\n\n```diff\ndiff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp\nindex 1ee3c03431..865dd3e9c3 100644\n--- a/src/bitcoin-cli.cpp\n+++ b/src/bitcoin-cli.cpp\n@@ -1517,10 +1517,12 @@ static void ParseGetInfoResult(UniValue& result)\n     }\n\n     const UniValue& warnings_value{result[\"warnings\"]};\n-    const std::string warnings{warnings_value.isArray()\n-        ? Join(warnings_value.getValues(), \"\\n\", [](const UniValue& warning) { return warning.get_str(); })\n-        : warnings_value.getValStr()};\n-    result_string += strprintf(\"%sWarnings:%s %s\", YELLOW, RESET, warnings.empty() ? \"(none)\" : warnings);\n+    if (warnings_value.isArray() && !warnings_value.empty()) {\n+        result_string += strprintf(\"%sWarnings%s\\n%s\", YELLOW, RESET, Join(warnings_value.getValues(), \"\\n\", [](const UniValue& warning) { return warning.get_str(); }));\n+    } else {\n+        const std::string warnings{warnings_value.getValStr()};\n+        result_string += strprintf(\"%sWarnings:%s %s\", YELLOW, RESET, warnings.empty() ? \"(none)\" : warnings);\n+    }\n\n     result.setStr(result_string);\n }\ndiff --git a/test/functional/interface_bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py\nindex 47e9bdd4bd..cf07eec3fe 100755\n--- a/test/functional/interface_bitcoin_cli.py\n+++ b/test/functional/interface_bitcoin_cli.py\n@@ -48,10 +48,12 @@ def cli_get_info_string_to_dict(cli_get_info_string):\n     line_idx = 0\n     while line_idx < len(lines):\n         line = lines[line_idx]\n-        if line.startswith(\"Warnings: \"):\n-            # Warnings is the final section and can span multiple lines.\n-            cli_get_info[\"Warnings\"] = \"\\n\".join(lines[line_idx:]).removeprefix(\"Warnings: \")\n-            break\n+        if line == \"Warnings\":\n+            # When \"Warnings\" is a header line, all of the following lines contain one warning until an empty line\n+            cli_get_info[\"Warnings\"] = []\n+            while line_idx + 1 < len(lines) and lines[line_idx + 1] != '':\n+                line_idx += 1\n+                cli_get_info[\"Warnings\"].append(lines[line_idx])\n         elif \"Balances\" in line:\n             # When \"Balances\" appears in a line, all of the following lines contain \"balance: wallet\" until an empty line\n             cli_get_info[\"Balances\"] = {}\n@@ -243,8 +245,7 @@ class TestBitcoinCli(BitcoinTestFramework):\n         assert_equal(cli_get_info['Proxies'], network_info['networks'][0]['proxy'])\n         assert_equal(Decimal(cli_get_info['Difficulty']), blockchain_info['difficulty'])\n         assert_equal(cli_get_info['Chain'], blockchain_info['chain'])\n-        expected_warnings = \"\\n\".join(network_info['warnings']) or \"(none)\"\n-        assert_equal(cli_get_info['Warnings'], expected_warnings)\n+        assert_equal(cli_get_info['Warnings'], network_info['warnings'] or \"(none)\")\n\n         self.log.info(\"Test -getinfo and bitcoin-cli return all proxies\")\n         self.restart_node(0, extra_args=[\"-proxy=127.0.0.1:9050\", \"-i2psam=127.0.0.1:7656\"])\n\n```"
  },
  {
   "t": "2026-09-16T14:24:17Z",
   "kind": "review",
   "who": "stickies-v",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "59d0d24d6cb67a4ddfe9951846ea90db42e9ef6f",
   "text": "Can you please squash the 2 commits?"
  }
 ],
 "labels_log": [
  {
   "t": "2026-09-09T22:55:55Z",
   "action": "labeled",
   "label": "Scripts and tools",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 5507,
 "text_tokens_estimate": 1376,
 "changed_paths": [
  "src/bitcoin-cli.cpp",
  "test/functional/interface_bitcoin_cli.py"
 ],
 "files": [
  {
   "path": "src/bitcoin-cli.cpp",
   "add": 4,
   "del": 1
  },
  {
   "path": "test/functional/interface_bitcoin_cli.py",
   "add": 11,
   "del": 5
  }
 ],
 "test_lines": 16,
 "git": {
  "head": "59d0d24d6cb67a4ddfe9951846ea90db42e9ef6f",
  "head_matches_backup": true,
  "base": "fc4f35fdce4d65696be6bf34003dbcac1f2f64bf",
  "commits": [
   {
    "sha": "045bb80f3d",
    "subject": "cli: Display warning arrays in -getinfo",
    "files": 3,
    "add": 14,
    "del": 1
   },
   {
    "sha": "59d0d24d6c",
    "subject": "test: Parse getinfo warnings in CLI helper",
    "files": 2,
    "add": 10,
    "del": 14
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "319dd9db5e1f2048",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}