qa: Avoid extra tracebacks when exception is raised #35458

pull hodlinator wants to merge 3 commits into bitcoin:master from hodlinator:2026/06/simplify_tracebacks changing 7 files +65 −71
  1. hodlinator commented at 9:00 AM on June 4, 2026: contributor

    Clean up some cases in which we would trigger multiple tracebacks, which makes it unclear what issue is occuring (https://github.com/bitcoin/bitcoin/issues/31894#issuecomment-4616130031).

    CI log of this occurring: https://github.com/bitcoin/bitcoin/actions/runs/26907239657/job/79375388058?pr=35179

    <details><summary>Relevant log excerpt</summary>

     test  2026-06-03T19:28:28.119804Z TestFramework.node0 (DEBUG): TestNode.generate() dispatches `generate` call to `generatetoaddress` 
     test  2026-06-03T19:28:28.120483Z TestFramework (ERROR): Unexpected exception: 
                                       Traceback (most recent call last):
                                         File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/authproxy.py", line 165, in _get_response
                                           http_response = self.__conn.getresponse()
                                                           ^^^^^^^^^^^^^^^^^^^^^^^^^
                                         File "/usr/lib/python3.12/http/client.py", line 1448, in getresponse
                                           response.begin()
                                         File "/usr/lib/python3.12/http/client.py", line 336, in begin
                                           version, status, reason = self._read_status()
                                                                     ^^^^^^^^^^^^^^^^^^^
                                         File "/usr/lib/python3.12/http/client.py", line 297, in _read_status
                                           line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                         File "/usr/lib/python3.12/socket.py", line 707, in readinto
                                           return self._sock.recv_into(b)
                                                  ^^^^^^^^^^^^^^^^^^^^^^^
                                       TimeoutError: timed out
                                       During handling of the above exception, another exception occurred:
                                       Traceback (most recent call last):
                                         File "/home/runner/work/bitcoin/bitcoin/ci_build/test/functional/p2p_orphan_handling.py", line 54, in wrapper
                                           func(self)
                                         File "/home/runner/work/bitcoin/bitcoin/ci_build/test/functional/p2p_orphan_handling.py", line 633, in test_maximal_package_protected
                                           testres = node.testmempoolaccept([large_orphan.serialize().hex()])
                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                         File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/coverage.py", line 50, in __call__
                                           return_val = self.auth_service_proxy_instance.__call__(*args, **kwargs)
                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                         File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/authproxy.py", line 128, in __call__
                                           response, status = self._request('POST', self.__url.path, postdata.encode('utf-8'))
                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                         File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/authproxy.py", line 102, in _request
                                           return self._get_response()
                                                  ^^^^^^^^^^^^^^^^^^^^
                                         File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/authproxy.py", line 167, in _get_response
                                           raise JSONRPCException({
                                       test_framework.util.JSONRPCException: 'testmempoolaccept' RPC took longer than 30.000000 seconds. Consider using larger timeout for calls that take longer to return. (-344)  [http_status=None]
                                       During handling of the above exception, another exception occurred:
                                       Traceback (most recent call last):
                                         File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/test_framework.py", line 143, in main
                                           self.run_test()
                                         File "/home/runner/work/bitcoin/bitcoin/ci_build/test/functional/p2p_orphan_handling.py", line 837, in run_test
                                           self.test_maximal_package_protected()
                                         File "/home/runner/work/bitcoin/bitcoin/ci_build/test/functional/p2p_orphan_handling.py", line 57, in wrapper
                                           self.generate(self.nodes[0], 1)
                                         File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/test_framework.py", line 666, in generate
                                           blocks = generator.generate(*args, called_by_framework=True, **kwargs)
                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                         File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/test_node.py", line 445, in generate
                                           return self.generatetoaddress(nblocks=nblocks, address=self.get_deterministic_priv_key().address, maxtries=maxtries, **kwargs)
                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                         File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/test_node.py", line 453, in generatetoaddress
                                           return self.__getattr__('generatetoaddress')(*args, **kwargs)
                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                         File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/coverage.py", line 50, in __call__
                                           return_val = self.auth_service_proxy_instance.__call__(*args, **kwargs)
                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                         File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/authproxy.py", line 128, in __call__
                                           response, status = self._request('POST', self.__url.path, postdata.encode('utf-8'))
                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                         File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/authproxy.py", line 101, in _request
                                           self.__conn.request(method, path, postdata, headers)
                                         File "/usr/lib/python3.12/http/client.py", line 1356, in request
                                           self._send_request(method, url, body, headers, encode_chunked)
                                         File "/usr/lib/python3.12/http/client.py", line 1367, in _send_request
                                           self.putrequest(method, url, **skips)
                                         File "/usr/lib/python3.12/http/client.py", line 1193, in putrequest
                                           raise CannotSendRequest(self.__state)
                                       http.client.CannotSendRequest: Request-sent
     test  2026-06-03T19:28:28.124908Z TestFramework (DEBUG): Closing down network thread 
    

    </details>

    Fix in authproxy.py can be verified through applying the below diff with/without PR changes and running ./build/test/functional/p2p_orphan_handling.py:

    --- a/test/functional/test_framework/authproxy.py
    +++ b/test/functional/test_framework/authproxy.py
    @@ -162,6 +162,8 @@ class AuthServiceProxy():
         def _get_response(self):
             req_start_time = time.time()
             try:
    +            if AuthServiceProxy.__id_count > 55:
    +                raise socket.timeout()
                 http_response = self.__conn.getresponse()
             except socket.timeout:
                 raise JSONRPCException({
    
  2. qa: Avoid cleanup when exception is raised
    If an exception is raised before we get to cleanup, do not swallow it and attempt to reset the state. Doing so could trigger knock-on exceptions and extra tracebacks.
    659671ac3d
  3. qa: Silence socket.timeout exception when substituting it for a JSONRPCException
    This prevents "During handling of the above exception, another exception occurred:" and an extra traceback.
    f42226d526
  4. DrahtBot added the label Tests on Jun 4, 2026
  5. DrahtBot commented at 9:01 AM on June 4, 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/35458.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    ACK polespinasa

    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.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #35302 (Silent Payments: Sending (take 2) by Eunovo)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  6. polespinasa commented at 9:10 AM on June 4, 2026: member

    Thanks for the PR!

    Fix in authproxy.py can be verified through applying the below diff with/without PR changes and running ./build/test/functional/p2p_orphan_handling.py

    How can I test this? I am only getting the failure in #35179 CI. Locally it does not fail for me.

  7. hodlinator commented at 10:31 AM on June 4, 2026: contributor

    Thanks for the PR!

    Fix in authproxy.py can be verified through applying the below diff with/without PR changes and running ./build/test/functional/p2p_orphan_handling.py

    How can I test this? I am only getting the failure in #35179 CI. Locally it does not fail for me.

    Have you tried applying the diff at the bottom of #35458#issue-4587336378 and running ./build/test/functional/p2p_orphan_handling.py?

  8. polespinasa commented at 3:36 PM on June 4, 2026: member

    tested ACK f42226d526ebb3eb9217e738108e4f8148a1b069

    Looks useful and makes it easier to identify errors.

  9. in test/functional/p2p_opportunistic_1p1c.py:66 in 659671ac3d
      73 | +        func(self, *args, **kwargs)
      74 | +
      75 | +        self.nodes[0].disconnect_p2ps()
      76 | +        # Do not clear the node's mempool, as each test requires mempool min feerate > min
      77 | +        # relay feerate. However, do check that this is the case.
      78 | +        assert self.nodes[0].getmempoolinfo()["mempoolminfee"] > self.nodes[0].getnetworkinfo()["relayfee"]
    


    polespinasa commented at 3:39 PM on June 4, 2026:

    nit: maybe an opportunity to change it to assert_greater_than()


    hodlinator commented at 8:02 PM on June 10, 2026:

    Added as a third commit but DrahtBot gets the credits in the commit message. :)

    Edit: DrahtBot suggestion in older version of #35458 (comment):

    Possible places where comparison-specific test macros should replace generic comparisons:

    [test/functional/p2p_opportunistic_1p1c.py] assert self.nodes[0].getmempoolinfo()["mempoolminfee"] > self.nodes[0].getnetworkinfo()["relayfee"] -> use assert_greater_than(self.nodes[0].getmempoolinfo()["mempoolminfee"], self.nodes[0].getnetworkinfo()["relayfee"])

    2026-06-04 09:01:15

  10. qa: Use custom assert_greater_than() over naked assert
    Co-authored-by: DrahtBot <39886733+DrahtBot@users.noreply.github.com>
    472b950b7f
  11. polespinasa commented at 8:10 PM on June 10, 2026: member

    reACK 472b950b7f799a5d336b1be4e4036deeb86ca0be


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-06-11 10:51 UTC

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