neondatabase/neon · error
File size {request_len} exceeds max {max_len}
Error message
File size {request_len} exceeds max {max_len} What it means
endpoint_storage's PUT handler buffers the whole request body in memory and rejects uploads larger than the configured max_upload_file_limit, returning a 400 with this message. The limit exists because remote_storage has no multipart support, so the service must hold the entire object in memory; the default is 100 MiB (100 * 1024 * 1024), configurable via the max_upload_file_limit field in the service's JSON config.
Source
Thrown at endpoint_storage/src/app.rs:93
.status(StatusCode::OK)
.header(CONTENT_TYPE, APPLICATION_OCTET_STREAM)
.body(Body::from_stream(stream))
.map_err(|e| internal_error(e, path, "reading response"))
}
// Best solution for files is multipart upload, but remote_storage doesn't support it,
// so we can either read Bytes in memory and push at once or forward BodyDataStream to
// remote_storage. The latter may seem more peformant, but BodyDataStream doesn't have a
// guaranteed size() which may produce issues while uploading to s3.
// So, currently we're going with an in-memory copy plus a boundary to prevent uploading
// very large files.
async fn set(S3Path { path }: S3Path, state: State, bytes: Bytes) -> Result {
info!(%path, "uploading");
let request_len = bytes.len();
let max_len = state.max_upload_file_limit;
if request_len > max_len {
return Err(bad_request(
anyhow!("File size {request_len} exceeds max {max_len}"),
"uploading",
));
}
let cancel = state.cancel.clone();
let fun = async || {
let stream = bytes_to_stream(bytes.clone());
state
.storage
.upload(stream, request_len, &path, None, &cancel)
.await
};
retry(
fun,
TimeoutOrCancel::caused_by_cancel,
WARN_THRESHOLD,
MAX_RETRIES,
"uploading",View on GitHub (pinned to 8f60b04da4)
Solutions
- Reduce the upload size below the service's limit
- Raise max_upload_file_limit in the endpoint_storage JSON config and restart the service (mind the memory footprint — bodies are held in memory)
- Split or compress the artifact so it fits under the configured bound
Example fix
// endpoint_storage config (main.rs reads JSON config)
// before
{ "pemfile": "/pem", "listen": "0.0.0.0:51243", "storage_kind": {"S3": {...}} }
// after
{ "pemfile": "/pem", "listen": "0.0.0.0:51243", "max_upload_file_limit": 524288000, "storage_kind": {"S3": {...}} } Defensive patterns
Strategy: validation
Validate before calling
// Client-side check before PUT: know the service's limit and your body size
let body_len = bytes.len();
if body_len > MAX_UPLOAD_FILE_LIMIT {
return Err(anyhow::anyhow!(
"body is {body_len} bytes, service limit is {MAX_UPLOAD_FILE_LIMIT}; split or raise max_upload_file_limit"
));
}
// or, when the limit is discoverable, compare Content-Length against it before sending Try / catch
match resp.status() {
StatusCode::BAD_REQUEST if body_contains(&resp, "exceeds max").await => {
// permanent: do not retry; shrink payload or raise the server's max_upload_file_limit
return Err(UploadTooLarge.into());
}
s if s.is_server_error() => { /* retryable */ }
_ => {}
} Prevention
- Agree on an explicit size contract (the server's max_upload_file_limit) with clients before uploading
- Check file size locally before starting a large PUT to avoid buffering 100+ MiB for a guaranteed 400
- Remember the whole body is held in server memory when tuning the limit
When it happens
Trigger: PUT-ing a body whose length exceeds state.max_upload_file_limit to the endpoint_storage HTTP endpoint (e.g. an extension artifact upload). The size check runs before any storage call and returns bad_request.
Common situations: Uploading large custom extensions or binaries above 100 MiB to a deployment running the default limit; a config that lowered the limit for memory protection; clients that do not check Content-Length against the service's limit before sending.
Related errors
- uploading cancelled
- deleting cancelled
- deleting prefix cancelled
- Read back file doesn't match original
- Supply either config file path or --config=inline-config
AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16).
Data as JSON: /api/errors/5c9ff804bff894cc.
Report an issue: GitHub.