← oracle_refix

requests_6629

failed WRONG_FIX UNSUBMITTED wrong_fix_unsubmitted(None) · None tool calls · 0 s · psf/requests

Task input

Fix #6628 - JSONDecodeError are not deserializable

See issue #6628 for full bug-report

-----

requests.exceptions.JSONDecodeError are not deserializable: calling `pickle.dumps` followed by `pickle.loads` will trigger an error.

This is particularly a problem in a process pool, as an attempt to decode json on an invalid json document will result in the entire process pool crashing.

This is due to the MRO of the `requests.exceptions.JSONDecodeError` class: the `__reduce__` method called when pickling an instance is not the one from the JSON library parent: two out of three args expected for instantiation will be dropped, and the instance can't be deserialised.

By specifying in the class which parent `__reduce__` method should be called, the bug is fixed as all args are carried over in the resulting pickled bytes.

Tool calls (0)

#ToolArgumentsResult
No trace captured.

Patch

--- a/src/requests/exceptions.py
+++ b/src/requests/exceptions.py
@@ -41,6 +41,16 @@ def __init__(self, *args, **kwargs):
         CompatJSONDecodeError.__init__(self, *args)
         InvalidJSONError.__init__(self, *self.args, **kwargs)
 
+    def __reduce__(self):
+        """
+        The __reduce__ method called when pickling the object must
+        be the one from the JSONDecodeError (be it json/simplejson)
+        as it expects all the arguments for instantiation, not just
+        one like the IOError, and the MRO would by default call the
+        __reduce__ method from the IOError due to the inheritance order.
+        """
+        return CompatJSONDecodeError.__reduce__(self)
+
 
 class HTTPError(RequestException):
     """An HTTP error occurred."""

Test output

show
NOWN_CA] tlsv1 alert unknown ca (_ssl.c:1032)
attempting to ignore so the rest of the tests can run
........................ [ 44%]
........................................................................ [ 66%]
..............x......................................................... [ 89%]
....................F
=================================== FAILURES ===================================
_ TestPreparingURLs.test_redirecting_to_bad_url[http://localhost:-1-InvalidURL] _

self = <tests.test_requests.TestPreparingURLs object at 0x104c77800>
httpbin = <function prepare_url.<locals>.inner at 0x103d600e0>
url = 'http://localhost:-1'
exception = <class 'requests.exceptions.InvalidURL'>

    @pytest.mark.parametrize("url, exception", (("http://localhost:-1", InvalidURL),))
    def test_redirecting_to_bad_url(self, httpbin, url, exception):
>       with pytest.raises(exception):
             ^^^^^^^^^^^^^^^^^^^^^^^^
E       Failed: DID NOT RAISE InvalidURL

tests/test_requests.py:2707: Failed
----------------------------- Captured stderr call -----------------------------
Traceback (most recent call last):
  File "/Users/jp/.local/share/uv/python/cpython-3.13.15-macos-aarch64-none/lib/python3.13/wsgiref/handlers.py", line 137, in run
    self.result = application(self.environ, self.start_response)
                  ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jp/repos/kaggle-gemini-coding-agent-post-training/.envs/requests/lib/python3.13/site-packages/flask/app.py", line 1536, in __call__
    return self.wsgi_app(environ, start_response)
           ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jp/repos/kaggle-gemini-coding-agent-post-training/.envs/requests/lib/python3.13/site-packages/flask/app.py", line 1518, in wsgi_app
    return response(environ, start_response)
  File "/Users/jp/repos/kaggle-gemini-coding-agent-post-training/.envs/requests/lib/python3.13/site-packages/werkzeug/wrappers/response.py", line 576, in __call__
    app_iter, status, headers = self.get_wsgi_response(environ)
                                ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/Users/jp/repos/kaggle-gemini-coding-agent-post-training/.envs/requests/lib/python3.13/site-packages/werkzeug/wrappers/response.py", line 562, in get_wsgi_response
    headers = self.get_wsgi_headers(environ)
  File "/Users/jp/repos/kaggle-gemini-coding-agent-post-training/.envs/requests/lib/python3.13/site-packages/werkzeug/wrappers/response.py", line 481, in get_wsgi_headers
    location = iri_to_uri(location)
  File "/Users/jp/repos/kaggle-gemini-coding-agent-post-training/.envs/requests/lib/python3.13/site-packages/werkzeug/urls.py", line 153, in iri_to_uri
    if parts.port:
       ^^^^^^^^^^
  File "/Users/jp/.local/share/uv/python/cpython-3.13.15-macos-aarch64-none/lib/python3.13/urllib/parse.py", line 182, in port
    raise ValueError(f"Port could not be cast to integer value as {port!r}")
ValueError: Port could not be cast to integer value as '-1'
127.0.0.1 - - [23/Sep/2026 18:24:20] "GET /redirect-to?url=http%3A%2F%2Flocalhost%3A-1 HTTP/1.1" 500 59
=============================== warnings summary ===============================
../../../../../../../Users/jp/repos/kaggle-gemini-coding-agent-post-training/.envs/requests/lib/python3.13/site-packages/_pytest/config/__init__.py:1464
  /Users/jp/repos/kaggle-gemini-coding-agent-post-training/.envs/requests/lib/python3.13/site-packages/_pytest/config/__init__.py:1464: PytestConfigWarning: Unknown config option: timeout
  
    self._warn_or_fail_if_strict(f"Unknown config option: {key}\n")

tests/test_requests.py::TestRequests::test_set_basicauth[42-42]
tests/test_requests.py::TestRequests::test_set_basicauth[42-42]
  /tmp/swe_work/oracle_refix/requests_6629/b/workspace/src/requests/auth.py:36: DeprecationWarning: Non-string usernames will no longer be supported in Requests 3.0.0. Please convert the object you've passed in (42) to a string or bytes object in the near future to avoid problems.
    warnings.warn(

tests/test_requests.py::TestRequests::test_set_basicauth[42-42]
tests/test_requests.py::TestRequests::test_set_basicauth[42-42]
  /tmp/swe_work/oracle_refix/requests_6629/b/workspace/src/requests/auth.py:46: DeprecationWarning: Non-string passwords will no longer be supported in Requests 3.0.0. Please convert the object you've passed in (<class 'int'>) to a string or bytes object in the near future to avoid problems.
    warnings.warn(

tests/test_requests.py::TestRequests::test_set_basicauth[None-None]
tests/test_requests.py::TestRequests::test_set_basicauth[None-None]
  /tmp/swe_work/oracle_refix/requests_6629/b/workspace/src/requests/auth.py:36: DeprecationWarning: Non-string usernames will no longer be supported in Requests 3.0.0. Please convert the object you've passed in (None) to a string or bytes object in the near future to avoid problems.
    warnings.warn(

tests/test_requests.py::TestRequests::test_set_basicauth[None-None]
tests/test_requests.py::TestRequests::test_set_basicauth[None-None]
  /tmp/swe_work/oracle_refix/requests_6629/b/workspace/src/requests/auth.py:46: DeprecationWarning: Non-string passwords will no longer be supported in Requests 3.0.0. Please convert the object you've passed in (<class 'NoneType'>) to a string or bytes object in the near future to avoid problems.
    warnings.warn(

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!
1 failed, 306 passed, 1 skipped, 1 xfailed, 9 warnings in 31.64s
[2026-09-23 18:23:49,693] WARNING in core: flasgger is not installed; serving the static landing page at / and skipping the Swagger UI and /spec.json.
127.0.0.1 - - [23/Sep/2026 18:23:50] "GET /get HTTP/1.1" 200 272
127.0.0.1 - - [23/Sep/2026 18:23:50] "GET /get?foo=f%C3%B8%C3%B8 HTTP/1.1" 200 320
127.0.0.1 - - [23/Sep/2026 18:23:50] "POST /post HTTP/1.1" 200 105449
127.0.0.1 - - [23/Sep/2026 18:24:00] "GET /get HTTP/1.1" 200 272