doc/test: several `HelpExampleRpc` curl examples emit invalid JSON; add a regression check to rpc_help.py #35864

issue GuTS805 opened this issue on August 1, 2026
  1. GuTS805 commented at 9:51 PM on August 1, 2026: none

    HelpExampleRpc interpolates its args string directly into a JSON-RPC payload (src/rpc/util.cpp:201-204) with no validation that the result is a well-formed JSON array body. On master (556988790a), 13 of the 138 literal HelpExampleRpc call sites produce a payload that fails JSON parsing, so the documented curl command is unusable as printed.

    Three failure modes:

    Missing comma separators (CLI-style arg string reused in the RPC example):

    • src/rpc/blockchain.cpp:543 getblockfrompeer
    • src/rpc/net.cpp:338 addnode
    • src/rpc/net.cpp:413 addconnection
    • src/rpc/net.cpp:1086 sendmsgtopeer
    • src/wallet/rpc/backup.cpp:628 restorewallet

    addnode shows this is an oversight rather than style — it has the first comma and is missing only the second:

    HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\" true")
    • HelpExampleRpc("addnode", ""192.168.0.6:8333", "onetry" true")

    renders "params": ["192.168.0.6:8333", "onetry" true]Expecting ',' delimiter: line 1 column 99

    Bare unquoted strings (valid as a CLI placeholder, a syntax error in JSON): src/rpc/mempool.cpp:871 getmempoolcluster, src/rpc/mempool.cpp:1171 importmempool, src/rpc/node.cpp:381 getindexinfo, src/wallet/rpc/addresses.cpp:646 listlabels, src/wallet/rpc/wallet.cpp:454 unloadwallet, src/wallet/rpc/wallet.cpp:774 createwalletdescriptor, src/wallet/rpc/wallet.cpp:864 addhdkey.

    Invalid backslash escape — src/wallet/rpc/wallet.cpp:246 loadwallet, the "absolute path (Windows)" example renders "params": ["DriveLetter:\path\to\walletname\"]Invalid \escape. The trailing \" also escapes the closing quote. The sibling CLI example on line 245 is correct as-is; only the JSON form needs the backslashes doubled.

    Why file this now rather than another round of manual fixes

    In #31275 sipa ran the runtime version of this check ("I wanted to verify if all invocations of HelpExampleRpc produce valid JSON, so I tested by adding a UniValue::read inside the function", 2025-11-10) and listed 11 failing RPCs. That list is an exact subset of the 13 above. Since then:

    RPC landed on master vs. the 2025-11-10 audit
    getmempoolcluster 2025-11-25 (fa283d28e2, #33629) +15 days
    addhdkey 2026-05-14 (cad5f56045, #29136) +6 months

    None of the original 11 were fixed, two more were added, and #31275 was closed unmerged on 2026-03-14 — addhdkey's example landed two months after that. Six separate PRs have fixed instances of this one-by-one over the years and the population still grows, because nothing enforces it.

    Proposed direction

    1. Add the guard first. test/functional/rpc_help.py::dump_help() already iterates every registered command and calls self.nodes[0].help(call). Extend it to extract each > curl ... --data-binary '<payload>' line from the help text and assert json.loads(payload) succeeds. Roughly ten lines, no new test file, covers every current and future RPC, and would have caught all 13 — including the ~16 call sites whose args are built from expressions (EXAMPLE_ADDRESS, strprintf, …) that a static scan has to skip. This is sipa's second suggestion from #31275.
    2. Then fix the 13: add the missing commas, quote the bare placeholders, and double the backslashes in the loadwallet Windows example.

    Worth settling direction before anyone writes a patch: sipa's first suggestion was to drop the curl examples entirely, which would moot the fixes. Happy to open a PR for whichever the maintainers prefer.

  2. GuTS805 commented at 9:51 PM on August 1, 2026: none

    I'd be happy to submit a PR for this starting with the rpc_help.py regression check (per sipa's suggestion in #31275), then fixing the 13 examples once that's merged and passing. Let me know if you'd rather go with dropping the curl examples entirely instead, per sipa's other suggestion.

  3. 650DataNerd commented at 7:43 AM on August 2, 2026: none

    Tried implementing the dump_help() extension suggested above (regex-extract the curl --data-binary payload, json.loads() it) and ran it against current master. It caught getblockfrompeer on the first run same missing-comma pattern as the addnode example, different call site:

    AssertionError: HelpExampleRpc for 'getblockfrompeer' is not valid JSON: Expecting ',' delimiter: line 1 column 146 (char 145)

    So the approach checks out independent of the 13 already listed above.

  4. GuTS805 commented at 8:47 AM on August 2, 2026: none

    Nice, thanks for verifying independently! Since the approach checks out, I'll go ahead and open a PR with the rpc_help.py extension plus the fixes for all 13.


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-08-10 11:50 UTC

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