Http2: stream closed and H3_REQUEST_CANCELLED

2025-02-10T15:40:21.563093413Z {"level":"debug","ts":1739202021.562953,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"jellyfin:8096","duration":0.016771721,"request":{"remote_ip":"10.0.0.20","remote_port":"46728","client_ip":"10.0.0.20","proto":"HTTP/2.0","method":"GET","host":"jf.domain.tld","uri":"/Videos/157fb2ae-1a95-2b35-7357-c29b556cbd50/stream?static=true&playSessionId=78aa361f3ec14ab0ae45b41fb7171415&mediaSourceId=157fb2ae1a952b357357c29b556cbd50&deviceId=7693145f6bd466dafe622119623f416d9ccafc213afd09d9&streamOptions=%7B%7D","headers":{"X-Forwarded-For":["10.0.0.20"],"X-Forwarded-Proto":["https"],"X-Forwarded-Host":["jf.domain.tld"],"User-Agent":["Jellyfin Android/2.6.2 (Linux;Android 15) ExoPlayerLib/2.19.1"],"Accept-Encoding":["gzip, deflate, br"],"Icy-Metadata":["1"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"jf.domain.tld"}},"headers":{"Server":["Kestrel"],"Accept-Ranges":["bytes"],"Last-Modified":["Sun, 24 Dec 2023 22:11:18 GMT"],"X-Response-Time-Ms":["16.4132"],"Content-Length":["120576935820"],"Content-Type":["video/x-matroska"],"Date":["Mon, 10 Feb 2025 15:40:20 GMT"]},"status":200}
2025-02-10T15:40:21.587617467Z {"level":"error","ts":1739202021.5875251,"logger":"http.handlers.reverse_proxy","msg":"aborting with incomplete response","upstream":"jellyfin:8096","duration":0.016771721,"request":{"remote_ip":"10.0.0.20","remote_port":"46728","client_ip":"10.0.0.20","proto":"HTTP/2.0","method":"GET","host":"jf.domain.tld","uri":"/Videos/157fb2ae-1a95-2b35-7357-c29b556cbd50/stream?static=true&playSessionId=78aa361f3ec14ab0ae45b41fb7171415&mediaSourceId=157fb2ae1a952b357357c29b556cbd50&deviceId=7693145f6bd466dafe622119623f416d9ccafc213afd09d9&streamOptions=%7B%7D","headers":{"X-Forwarded-For":["10.0.0.20"],"X-Forwarded-Proto":["https"],"X-Forwarded-Host":["jf.domain.tld"],"User-Agent":["Jellyfin Android/2.6.2 (Linux;Android 15) ExoPlayerLib/2.19.1"],"Accept-Encoding":["gzip, deflate, br"],"Icy-Metadata":["1"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"jf.domain.tld"}},"error":"writing: http2: stream closed"}

This tells me that Caddy is properly forwarding its request. The client requests the video stream and the server responds with a 200 OK, indicating it’s sending the file. However, the connection is abruptly closed during transmission.

I believe this issue lies with Jellyfin and the configuration or plugins. Otherwise, it’s the networking or firewalls. There’s more to the networking configuration than just the bridge mode. You specified it as an external network, which means it was created outside of the compose.yaml file. Use

docker network inspect jellyfin_default

to show the configuration of it. Is Jellyfin on the host machine or also configured in Docker Compose?