#1140980 httpx: FTBFS: E assert [('uvicorn.ac...1.1 200 OK"')] == [('httpx', 20...1.1 200 OK"')]

Package:
src:httpx
Source:
src:httpx
Submitter:
Santiago Vila
Date:
2026-06-28 20:54:15 UTC
Severity:
normal
Tags:
#1140980#5
Date:
2026-06-28 20:51:11 UTC
From:
To:
Dear maintainer:

During a rebuild of all packages in unstable, this package failed to build.

Below you will find the last part of the build log (probably the most
relevant part, but not necessarily). If required, the full build log
is available here:

https://people.debian.org/~sanvila/build-logs/202606/

About the archive rebuild: The build was made on virtual machines from AWS,
using sbuild and a reduced chroot with only build-essential packages.

If you cannot reproduce the bug please contact me privately, as I
am willing to provide ssh access to a virtual machine where the bug is
fully reproducible.

If this is really a bug in one of the build-depends, please use
reassign and add an affects on src:httpx, so that this is still
visible in the BTS web page for this package.

Thanks.
--------------------------------------------------------------------------------
[...]
 debian/rules clean
dh clean --with python3 --buildsystem=pybuild
   dh_auto_clean -O--buildsystem=pybuild
   dh_autoreconf_clean -O--buildsystem=pybuild
   dh_clean -O--buildsystem=pybuild
 debian/rules binary
dh binary --with python3 --buildsystem=pybuild
   dh_update_autotools_config -O--buildsystem=pybuild
   dh_autoreconf -O--buildsystem=pybuild
   dh_auto_configure -O--buildsystem=pybuild
   dh_auto_build -O--buildsystem=pybuild
I: pybuild plugin_pyproject:142: Building wheel for python3.13 with "build" module
I: pybuild base:385: python3.13 -m build --skip-dependency-check --no-isolation --wheel --outdir /<<PKGBUILDDIR>>/.pybuild/cpython3_3.13_httpx
* Building wheel...
Successfully built httpx-0.28.1-py3-none-any.whl

[... snipped ...]

tests/test_content.py::test_multipart_data_and_files_content[asyncio] PASSED [ 86%]
tests/test_content.py::test_empty_request[asyncio] PASSED                [ 86%]
tests/test_content.py::test_multipart_multiple_files_single_input_content[asyncio] PASSED [ 86%]
tests/test_content.py::test_response_empty_content[asyncio] PASSED       [ 86%]
tests/test_content.py::test_response_bytes_content[asyncio] PASSED       [ 86%]
tests/test_content.py::test_response_iterator_content[asyncio] PASSED    [ 86%]
tests/test_content.py::test_response_aiterator_content[asyncio] PASSED   [ 87%]
tests/test_content.py::test_empty_content[trio] PASSED                   [ 87%]
tests/test_content.py::test_bytes_content[trio] PASSED                   [ 87%]
tests/test_content.py::test_bytesio_content[trio] PASSED                 [ 87%]
tests/test_content.py::test_async_bytesio_content[trio] PASSED           [ 87%]
tests/test_content.py::test_iterator_content[trio] PASSED                [ 87%]
tests/test_content.py::test_aiterator_content[trio] PASSED               [ 87%]
tests/test_content.py::test_json_content[trio] PASSED                    [ 87%]
tests/test_content.py::test_urlencoded_content[trio] PASSED              [ 87%]
tests/test_content.py::test_urlencoded_boolean[trio] PASSED              [ 87%]
tests/test_content.py::test_urlencoded_none[trio] PASSED                 [ 87%]
tests/test_content.py::test_urlencoded_list[trio] PASSED                 [ 87%]
tests/test_content.py::test_multipart_files_content[trio] PASSED         [ 87%]
tests/test_content.py::test_multipart_data_and_files_content[trio] PASSED [ 87%]
tests/test_content.py::test_empty_request[trio] PASSED                   [ 88%]
tests/test_content.py::test_multipart_multiple_files_single_input_content[trio] PASSED [ 88%]
tests/test_content.py::test_response_empty_content[trio] PASSED          [ 88%]
tests/test_content.py::test_response_bytes_content[trio] PASSED          [ 88%]
tests/test_content.py::test_response_iterator_content[trio] PASSED       [ 88%]
tests/test_content.py::test_response_aiterator_content[trio] PASSED      [ 88%]
tests/test_content.py::test_invalid_argument PASSED                      [ 88%]
tests/test_content.py::test_response_invalid_argument PASSED             [ 88%]
tests/test_content.py::test_ensure_ascii_false_with_french_characters PASSED [ 88%]
tests/test_content.py::test_separators_for_compact_json PASSED           [ 88%]
tests/test_content.py::test_allow_nan_false PASSED                       [ 88%]
tests/test_decoders.py::test_deflate PASSED                              [ 88%]
tests/test_decoders.py::test_zlib PASSED                                 [ 88%]
tests/test_decoders.py::test_gzip PASSED                                 [ 88%]
tests/test_decoders.py::test_brotli PASSED                               [ 89%]
tests/test_decoders.py::test_zstd PASSED                                 [ 89%]
tests/test_decoders.py::test_zstd_decoding_error PASSED                  [ 89%]
tests/test_decoders.py::test_zstd_empty PASSED                           [ 89%]
tests/test_decoders.py::test_zstd_truncated PASSED                       [ 89%]
tests/test_decoders.py::test_zstd_multiframe PASSED                      [ 89%]
tests/test_decoders.py::test_multi PASSED                                [ 89%]
tests/test_decoders.py::test_multi_with_identity PASSED                  [ 89%]
tests/test_decoders.py::test_streaming[asyncio] PASSED                   [ 89%]
tests/test_decoders.py::test_text_decoder_with_autodetect[asyncio-data0-ascii] PASSED [ 89%]
tests/test_decoders.py::test_text_decoder_with_autodetect[asyncio-data1-utf-8] PASSED [ 89%]
tests/test_decoders.py::test_text_decoder_with_autodetect[asyncio-data2-cp1252] PASSED [ 89%]
tests/test_decoders.py::test_text_decoder_with_autodetect[asyncio-data3-iso-8859-1] PASSED [ 89%]
tests/test_decoders.py::test_text_decoder_known_encoding[asyncio] PASSED [ 89%]
tests/test_decoders.py::test_streaming[trio] PASSED                      [ 90%]
tests/test_decoders.py::test_text_decoder_with_autodetect[trio-data0-ascii] PASSED [ 90%]
tests/test_decoders.py::test_text_decoder_with_autodetect[trio-data1-utf-8] PASSED [ 90%]
tests/test_decoders.py::test_text_decoder_with_autodetect[trio-data2-cp1252] PASSED [ 90%]
tests/test_decoders.py::test_text_decoder_with_autodetect[trio-data3-iso-8859-1] PASSED [ 90%]
tests/test_decoders.py::test_text_decoder_known_encoding[trio] PASSED    [ 90%]
tests/test_decoders.py::test_empty_content[deflate] PASSED               [ 90%]
tests/test_decoders.py::test_empty_content[gzip] PASSED                  [ 90%]
tests/test_decoders.py::test_empty_content[br] PASSED                    [ 90%]
tests/test_decoders.py::test_empty_content[identity] PASSED              [ 90%]
tests/test_decoders.py::test_decoders_empty_cases[deflate] PASSED        [ 90%]
tests/test_decoders.py::test_decoders_empty_cases[gzip] PASSED           [ 90%]
tests/test_decoders.py::test_decoders_empty_cases[br] PASSED             [ 90%]
tests/test_decoders.py::test_decoders_empty_cases[identity] PASSED       [ 90%]
tests/test_decoders.py::test_decoding_errors[deflate] PASSED             [ 91%]
tests/test_decoders.py::test_decoding_errors[gzip] PASSED                [ 91%]
tests/test_decoders.py::test_decoding_errors[br] PASSED                  [ 91%]
tests/test_decoders.py::test_text_decoder_empty_cases PASSED             [ 91%]
tests/test_decoders.py::test_streaming_text_decoder[data0-expected0] PASSED [ 91%]
tests/test_decoders.py::test_line_decoder_nl PASSED                      [ 91%]
tests/test_decoders.py::test_line_decoder_cr PASSED                      [ 91%]
tests/test_decoders.py::test_line_decoder_crnl PASSED                    [ 91%]
tests/test_decoders.py::test_invalid_content_encoding_header PASSED      [ 91%]
tests/test_exceptions.py::test_httpcore_all_exceptions_mapped PASSED     [ 91%]
tests/test_exceptions.py::test_httpcore_exception_mapping PASSED         [ 91%]
tests/test_exceptions.py::test_request_attribute PASSED                  [ 91%]
tests/test_exported_members.py::test_all_imports_are_exported PASSED     [ 91%]
tests/test_main.py::test_help PASSED                                     [ 91%]
tests/test_main.py::test_get PASSED                                      [ 92%]
tests/test_main.py::test_json PASSED                                     [ 92%]
tests/test_main.py::test_binary PASSED                                   [ 92%]
tests/test_main.py::test_redirects PASSED                                [ 92%]
tests/test_main.py::test_follow_redirects PASSED                         [ 92%]
tests/test_main.py::test_post PASSED                                     [ 92%]
tests/test_main.py::test_verbose PASSED                                  [ 92%]
tests/test_main.py::test_auth PASSED                                     [ 92%]
tests/test_main.py::test_download PASSED                                 [ 92%]
tests/test_main.py::test_errors PASSED                                   [ 92%]
tests/test_multipart.py::test_multipart[abc-abc0] PASSED                 [ 92%]
tests/test_multipart.py::test_multipart[abc-abc1] PASSED                 [ 92%]
tests/test_multipart.py::test_multipart_explicit_boundary[multipart/form-data; boundary=+++; charset=utf-8] PASSED [ 92%]
tests/test_multipart.py::test_multipart_explicit_boundary[multipart/form-data; charset=utf-8; boundary=+++] PASSED [ 92%]
tests/test_multipart.py::test_multipart_explicit_boundary[multipart/form-data; boundary=+++] PASSED [ 92%]
tests/test_multipart.py::test_multipart_explicit_boundary[multipart/form-data; boundary=+++ ;] PASSED [ 93%]
tests/test_multipart.py::test_multipart_explicit_boundary[multipart/form-data; boundary="+++"; charset=utf-8] PASSED [ 93%]
tests/test_multipart.py::test_multipart_explicit_boundary[multipart/form-data; charset=utf-8; boundary="+++"] PASSED [ 93%]
tests/test_multipart.py::test_multipart_explicit_boundary[multipart/form-data; boundary="+++"] PASSED [ 93%]
tests/test_multipart.py::test_multipart_explicit_boundary[multipart/form-data; boundary="+++" ;] PASSED [ 93%]
tests/test_multipart.py::test_multipart_header_without_boundary[multipart/form-data; charset=utf-8] PASSED [ 93%]
tests/test_multipart.py::test_multipart_header_without_boundary[multipart/form-data; charset=utf-8; ] PASSED [ 93%]
tests/test_multipart.py::test_multipart_invalid_key[abc] PASSED          [ 93%]
tests/test_multipart.py::test_multipart_invalid_key[1] PASSED            [ 93%]
tests/test_multipart.py::test_multipart_invalid_key[2.3] PASSED          [ 93%]
tests/test_multipart.py::test_multipart_invalid_key[None] PASSED         [ 93%]
tests/test_multipart.py::test_multipart_invalid_value[value0] PASSED     [ 93%]
tests/test_multipart.py::test_multipart_invalid_value[value1] PASSED     [ 93%]
tests/test_multipart.py::test_multipart_file_tuple PASSED                [ 93%]
tests/test_multipart.py::test_multipart_file_tuple_headers[None] PASSED  [ 94%]
tests/test_multipart.py::test_multipart_file_tuple_headers[text/plain] PASSED [ 94%]
tests/test_multipart.py::test_multipart_headers_include_content_type PASSED [ 94%]
tests/test_multipart.py::test_multipart_encode PASSED                    [ 94%]
tests/test_multipart.py::test_multipart_encode_unicode_file_contents PASSED [ 94%]
tests/test_multipart.py::test_multipart_encode_files_allows_filenames_as_none PASSED [ 94%]
tests/test_multipart.py::test_multipart_encode_files_guesses_correct_content_type[example.json-application/json] PASSED [ 94%]
tests/test_multipart.py::test_multipart_encode_files_guesses_correct_content_type[example.txt-text/plain] PASSED [ 94%]
tests/test_multipart.py::test_multipart_encode_files_guesses_correct_content_type[no-extension-application/octet-stream] PASSED [ 94%]
tests/test_multipart.py::test_multipart_encode_files_allows_bytes_content PASSED [ 94%]
tests/test_multipart.py::test_multipart_encode_files_allows_str_content PASSED [ 94%]
tests/test_multipart.py::test_multipart_encode_files_raises_exception_with_StringIO_content PASSED [ 94%]
tests/test_multipart.py::test_multipart_encode_files_raises_exception_with_text_mode_file PASSED [ 94%]
tests/test_multipart.py::test_multipart_encode_non_seekable_filelike PASSED [ 94%]
tests/test_multipart.py::test_multipart_rewinds_files PASSED             [ 95%]
tests/test_multipart.py::TestHeaderParamHTML5Formatting::test_unicode PASSED [ 95%]
tests/test_multipart.py::TestHeaderParamHTML5Formatting::test_ascii PASSED [ 95%]
tests/test_multipart.py::TestHeaderParamHTML5Formatting::test_unicode_escape PASSED [ 95%]
tests/test_multipart.py::TestHeaderParamHTML5Formatting::test_unicode_with_control_character PASSED [ 95%]
tests/test_status_codes.py::test_status_code_as_int PASSED               [ 95%]
tests/test_status_codes.py::test_status_code_value_lookup PASSED         [ 95%]
tests/test_status_codes.py::test_status_code_phrase_lookup PASSED        [ 95%]
tests/test_status_codes.py::test_lowercase_status_code PASSED            [ 95%]
tests/test_status_codes.py::test_reason_phrase_for_status_code PASSED    [ 95%]
tests/test_status_codes.py::test_reason_phrase_for_unknown_status_code PASSED [ 95%]
tests/test_timeouts.py::test_read_timeout[asyncio] PASSED                [ 95%]
tests/test_timeouts.py::test_write_timeout[asyncio] PASSED               [ 95%]
tests/test_timeouts.py::test_pool_timeout[asyncio] PASSED                [ 95%]
tests/test_timeouts.py::test_async_client_new_request_send_timeout[asyncio] PASSED [ 96%]
tests/test_timeouts.py::test_read_timeout[trio] PASSED                   [ 96%]
tests/test_timeouts.py::test_write_timeout[trio] PASSED                  [ 96%]
tests/test_timeouts.py::test_pool_timeout[trio] PASSED                   [ 96%]
tests/test_timeouts.py::test_async_client_new_request_send_timeout[trio] PASSED [ 96%]
tests/test_utils.py::test_encoded[utf-32] PASSED                         [ 96%]
tests/test_utils.py::test_encoded[utf-8-sig] PASSED                      [ 96%]
tests/test_utils.py::test_encoded[utf-16] PASSED                         [ 96%]
tests/test_utils.py::test_encoded[utf-8] PASSED                          [ 96%]
tests/test_utils.py::test_encoded[utf-16-be] PASSED                      [ 96%]
tests/test_utils.py::test_encoded[utf-16-le] PASSED                      [ 96%]
tests/test_utils.py::test_encoded[utf-32-be] PASSED                      [ 96%]
tests/test_utils.py::test_encoded[utf-32-le] PASSED                      [ 96%]
tests/test_utils.py::test_bad_utf_like_encoding PASSED                   [ 96%]
tests/test_utils.py::test_guess_by_bom[utf-16-be-utf-16] PASSED          [ 97%]
tests/test_utils.py::test_guess_by_bom[utf-16-le-utf-16] PASSED          [ 97%]
tests/test_utils.py::test_guess_by_bom[utf-32-be-utf-32] PASSED          [ 97%]
tests/test_utils.py::test_guess_by_bom[utf-32-le-utf-32] PASSED          [ 97%]
tests/test_utils.py::test_logging_request FAILED                         [ 97%]
tests/test_utils.py::test_logging_redirect_chain FAILED                  [ 97%]
tests/test_utils.py::test_get_environment_proxies[environment0-proxies0] PASSED [ 97%]
tests/test_utils.py::test_get_environment_proxies[environment1-proxies1] PASSED [ 97%]
tests/test_utils.py::test_get_environment_proxies[environment2-proxies2] PASSED [ 97%]
tests/test_utils.py::test_get_environment_proxies[environment3-proxies3] PASSED [ 97%]
tests/test_utils.py::test_get_environment_proxies[environment4-proxies4] PASSED [ 97%]
tests/test_utils.py::test_get_environment_proxies[environment5-proxies5] PASSED [ 97%]
tests/test_utils.py::test_get_environment_proxies[environment6-proxies6] PASSED [ 97%]
tests/test_utils.py::test_get_environment_proxies[environment7-proxies7] PASSED [ 97%]
tests/test_utils.py::test_get_environment_proxies[environment8-proxies8] PASSED [ 98%]
tests/test_utils.py::test_get_environment_proxies[environment9-proxies9] PASSED [ 98%]
tests/test_utils.py::test_get_environment_proxies[environment10-proxies10] PASSED [ 98%]
tests/test_utils.py::test_get_environment_proxies[environment11-proxies11] PASSED [ 98%]
tests/test_utils.py::test_url_matches[http://example.com-http://example.com-True] PASSED [ 98%]
tests/test_utils.py::test_url_matches[http://example.com-https://example.com-False] PASSED [ 98%]
tests/test_utils.py::test_url_matches[http://example.com-http://other.com-False] PASSED [ 98%]
tests/test_utils.py::test_url_matches[http://example.com:123-http://example.com:123-True] PASSED [ 98%]
tests/test_utils.py::test_url_matches[http://example.com:123-http://example.com:456-False] PASSED [ 98%]
tests/test_utils.py::test_url_matches[http://example.com:123-http://example.com-False] PASSED [ 98%]
tests/test_utils.py::test_url_matches[all://example.com-http://example.com-True] PASSED [ 98%]
tests/test_utils.py::test_url_matches[all://example.com-https://example.com-True] PASSED [ 98%]
tests/test_utils.py::test_url_matches[http://-http://example.com-True] PASSED [ 98%]
tests/test_utils.py::test_url_matches[http://-https://example.com-False] PASSED [ 98%]
tests/test_utils.py::test_url_matches[all://-https://example.com:123-True] PASSED [ 99%]
tests/test_utils.py::test_url_matches[-https://example.com:123-True] PASSED [ 99%]
tests/test_utils.py::test_pattern_priority PASSED                        [ 99%]
tests/test_wsgi.py::test_wsgi PASSED                                     [ 99%]
tests/test_wsgi.py::test_wsgi_upload PASSED                              [ 99%]
tests/test_wsgi.py::test_wsgi_upload_with_response_stream PASSED         [ 99%]
tests/test_wsgi.py::test_wsgi_exc PASSED                                 [ 99%]
tests/test_wsgi.py::test_wsgi_http_error PASSED                          [ 99%]
tests/test_wsgi.py::test_wsgi_generator PASSED                           [ 99%]
tests/test_wsgi.py::test_wsgi_generator_empty PASSED                     [ 99%]
tests/test_wsgi.py::test_logging PASSED                                  [ 99%]
tests/test_wsgi.py::test_wsgi_server_port[auto-http] PASSED              [ 99%]
tests/test_wsgi.py::test_wsgi_server_port[auto-https] PASSED             [ 99%]
tests/test_wsgi.py::test_wsgi_server_port[explicit-port] PASSED          [ 99%]
tests/test_wsgi.py::test_wsgi_server_protocol PASSED                     [100%]

=================================== FAILURES ===================================

            (
                "httpx",
                logging.INFO,
                'HTTP Request: GET http://127.0.0.1:8000/ "HTTP/1.1 200 OK"',
            )
        ]
E       assert [('uvicorn.ac...1.1 200 OK"')] == [('httpx', 20...1.1 200 OK"')]
E
E         At index 0 diff: ('uvicorn.access', 20, '127.0.0.1:52530 - "GET / HTTP/1.1" 200') != ('httpx', 20, 'HTTP Request: GET http://127.0.0.1:8000/ "HTTP/1.1 200 OK"')
E         Left contains one more item: ('httpx', 20, 'HTTP Request: GET http://127.0.0.1:8000/ "HTTP/1.1 200 OK"')
E
E         Full diff:
E           [
E         +     (...
E
E         ...Full output truncated (10 lines hidden), use '-vv' to show

tests/test_utils.py:59: AssertionError
----------------------------- Captured stdout call -----------------------------
INFO:     127.0.0.1:52530 - "GET / HTTP/1.1" 200 OK
------------------------------ Captured log call -------------------------------
INFO     uvicorn.access:h11_impl.py:473 127.0.0.1:52530 - "GET / HTTP/1.1" 200
INFO     httpx:_client.py:1025 HTTP Request: GET http://127.0.0.1:8000/ "HTTP/1.1 200 OK"

            (
                "httpx",
                logging.INFO,
                "HTTP Request: GET http://127.0.0.1:8000/redirect_301"
                ' "HTTP/1.1 301 Moved Permanently"',
            ),
            (
                "httpx",
                logging.INFO,
                'HTTP Request: GET http://127.0.0.1:8000/ "HTTP/1.1 200 OK"',
            ),
        ]
E       assert [('uvicorn.ac...1.1 200 OK"')] == [('httpx', 20...1.1 200 OK"')]
E
E         At index 0 diff: ('uvicorn.access', 20, '127.0.0.1:52544 - "GET /redirect_301 HTTP/1.1" 301') != ('httpx', 20, 'HTTP Request: GET http://127.0.0.1:8000/redirect_301 "HTTP/1.1 301 Moved Permanently"')
E         Left contains 2 more items, first extra item: ('uvicorn.access', 20, '127.0.0.1:52544 - "GET / HTTP/1.1" 200')
E
E         Full diff:
E           [
E         +     (...
E
E         ...Full output truncated (21 lines hidden), use '-vv' to show

tests/test_utils.py:74: AssertionError
----------------------------- Captured stdout call -----------------------------
INFO:     127.0.0.1:52544 - "GET /redirect_301 HTTP/1.1" 301 Moved Permanently
INFO:     127.0.0.1:52544 - "GET / HTTP/1.1" 200 OK
------------------------------ Captured log call -------------------------------
INFO     uvicorn.access:h11_impl.py:473 127.0.0.1:52544 - "GET /redirect_301 HTTP/1.1" 301
INFO     httpx:_client.py:1025 HTTP Request: GET http://127.0.0.1:8000/redirect_301 "HTTP/1.1 301 Moved Permanently"
INFO     uvicorn.access:h11_impl.py:473 127.0.0.1:52544 - "GET / HTTP/1.1" 200
INFO     httpx:_client.py:1025 HTTP Request: GET http://127.0.0.1:8000/ "HTTP/1.1 200 OK"
=========================== short test summary info ============================
SKIPPED [1] tests/client/test_auth.py:273: netrc files without a password are valid from Python >= 3.11
=========== 2 failed, 1410 passed, 1 skipped, 5 deselected in 4.40s ============
make[1]: *** [debian/rules:16: override_dh_auto_test] Error 1
make[1]: Leaving directory '/<<PKGBUILDDIR>>'
make: *** [debian/rules:12: binary] Error 2
dpkg-buildpackage: error: debian/rules binary subprocess failed with exit status 2
--------------------------------------------------------------------------------