mitmproxy / mitmproxy/mitmproxy

QUIC / HTTP3 breaks on large volume of requests to different hosts

Open
#8,043 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

kind/triage
Dominant language
Python
Stars
45.1k
Forks
4.7k
Avg merge
21h 12m
Merged PRs (30d)
16

Description

Problem Description

A large volume of QUIC requests to multiple hosts leads to lots of requests failing.

When transparently intercepting process traffic with mitmproxy, requests error out with "stream already ended" (compared to consistently flawless execution otherwise). Error is thrown from the following lines. https://github.com/mitmproxy/mitmproxy/blob/e6aa924bb411a9687b91920b8d094af37bc02b90/mitmproxy/proxy/layers/http/_http_h3.py#L230-L245

My guess is this is due to the large volume of QUERY requests / DNS queries - by the time the proxy starts processing the HTTP3 requests, the server has transmitted the proper data and closed the connection. I've made a minimal repo for reproduction.

Steps to reproduce the behavior:
  1. I have created a repo that sends ~300 requests to multiple hosts (Googleapis, and each is for a document. This won't cause any disruption, it's pretty static. And they're a big company) for reproduction purposes in https://github.com/bedros-p/quicmess - it is easy to review the source, as there isn't much to it.
  2. go build creates a binary quicmess. Run with quicmess multidomain.txt and confirm that there aren't any errors. This should take ~30 seconds and produce "All requests completed" at the end.
  3. mitmproxy -> Local Applications -> Intercept traffic for process quicmess
  4. Run the binary with ./quicmess multidomain.txt, see the errors stream already ended
  5. Run the binary with ./quicmess samedomain.txt, see the lack of errors.

Here is what it looks like, with the highlighting indicating the moment I start intercepting it.
Terminal showcasing the program running with a wordlist of multiple domains, twice, with no errors. After a highlighted line, the program is run again, but with an error this time. The highlighted line indicates when the intercepting began. The program is run again after that error, but this time all the requests are sent to the same domain, and there are no errors.

Here's mitmweb. After all the QUERYs, some make it through, then a couple don't. I couldn't find any patterns with the timings or size. Couldn't find any patterns to link with the entry preceding each error either.

Image
System Information
Mitmproxy: 12.2.1 binary
Python:    3.14.0
OpenSSL:   OpenSSL 3.5.4 30 Sep 2025
Platform:  Linux-6.8.0-90-generic-x86_64-with-glibc2.35
Checklist

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at mitmproxy/proxy/layers/http/_http_h3.py lines 230-245 and reproduce with quicmess: compare multidomain.txt under interception with samedomain.txt. Trace the HTTP/3 stream lifecycle around the reported "stream already ended" errors; done means the multidomain run completes without those failures.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.