element-hq / element-hq/synapse

If the upload of media files exceeds the `max_upload_size`, Synapse terminates the connection without returning an HTTP status code

Open
#20,022 1 comment 0 reactions 0 assignees View on GitHub
A-Media-Repository
Dominant language
Python
Stars
4.6k
Forks
600
Avg merge
5d 22h
Merged PRs (30d)
51

Description

### Description

If the upload of media files exceeds the `max_upload_size`, Synapse terminates the connection without returning an HTTP status code.

Synapse should respond with the correct status code `HTTP/413`.

Related Issue:
- #17053

### Steps to reproduce

Upload a file larger than limit:

```sh
curl 'https:///_matrix/media/v3/upload?filename=testvideo.mp4' -H 'Authorization: Bearer ' -H 'Content-Type: video/mp4' --data-binary @video.mp4 -v
* Host :443 was resolved.
* IPv6: (none)
* IPv4:
* Trying :443...
* Connected to () port 443
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / X25519 / RSASSA-PSS
* ALPN: server accepted h2
* Server certificate:
* subject: CN=
* start date: Jun 23 10:05:04 2026 GMT
* expire date: Sep 21 10:05:03 2026 GMT
* subjectAltName: host "" matched cert's ""
* issuer: C=US; O=Let's Encrypt; CN=YR1
* SSL certificate verify ok.
* Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 1: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 2: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 3: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https:///_matrix/media/v3/upload?filename=testvideo.mp4
* [HTTP/2] [1] [:method: POST]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: ]
* [HTTP/2] [1] [:path: /_matrix/media/v3/upload?filename=testvideo.mp4]
* [HTTP/2] [1] [user-agent: curl/8.5.0]
* [HTTP/2] [1] [accept: */*]
* [HTTP/2] [1] [authorization: Bearer ]
* [HTTP/2] [1] [content-type: video/mp4]
* [HTTP/2] [1] [content-length: 108864523]
> POST /_matrix/media/v3/upload?filename=testvideo.mp4 HTTP/2
> Host:
> User-Agent: curl/8.5.0
> Accept: */*
> Authorization: Bearer
> Content-Type: video/mp4
> Content-Length: 108864523
>
< HTTP/2 502
< content-length: 11
< date: Thu, 30 Jul 2026 13:30:03 GMT
* HTTP error before end of send, stop sending
<
* Connection #0 to host left intact
```

Ingress/Reverse Proxy terminates with `HTTP/2 502`, because Synapse closes the connection without response.

### Homeserver

private

### Synapse Version

1.157.2

### Installation Method

Docker (matrixdotorg/synapse)

### Database

PostgreSQL

### Workers

Multiple workers

### Platform

Kubernetes
Ingress: Traefik

### Configuration

`max_upload_size: 50M`

### Relevant log output

```shell
2026-07-30 13:30:03,334 - synapse.http.site - 306 - WARNING - sentinel - Aborting connection from IPv4Address(type='TCP', host='100.101.44.7', port=44152) because the request exceeds maximum size: (no method yet) (no uri yet)
2026-07-30 13:30:03,346 - synapse.http.site - 542 - INFO - sentinel - Connection from IPv4Address(type='TCP', host='100.101.44.7', port=44152) lost before request headers were read
```

### Anything else that would be useful to know?

affected code:

https://github.com/element-hq/synapse/blob/36664cac4fdec38993c68078cd9a82452b56dca7/synapse/http/site.py#L302-L315

I’d be happy to post an update. Is this the right place, or is there a more specific section for media uploads?

Contributor guide

Open the contributing guide

Research direction

Start in synapse/http/site.py around lines 302-315, then reproduce the oversized media upload with the curl command from the issue. Trace how the request-size limit is handled and verify that an upload exceeding max_upload_size returns HTTP 413 rather than closing without a response.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.