pinpoint-apm/pinpoint · warning
OTLP/HTTP trace request rejected. Unsupported Content-Encodi
Error message
OTLP/HTTP trace request rejected. Unsupported Content-Encoding={} What it means
OtlpTraceDecompressionFilter.doFilterInternal rejects OTLP/HTTP trace requests whose Content-Encoding is not 'gzip'. The OTLP/HTTP spec only defines gzip compression; anything else (identity mislabeled, deflate, br, or multi-encodings like 'gzip, br') is rejected up front with HTTP 415 UNSUPPORTED_MEDIA_TYPE so the caller gets an explicit error instead of an opaque 400 from a garbled undecoded protobuf body.
Source
Thrown at otlptrace/otlptrace-collector/src/main/java/com/navercorp/pinpoint/otlp/trace/collector/controller/OtlpTraceDecompressionFilter.java:93
public OtlpTraceDecompressionFilter(int maxDecompressedBytes, OtlpTraceIngestMetrics ingestMetrics) {
this.maxDecompressedBytes = maxDecompressedBytes;
this.ingestMetrics = Objects.requireNonNull(ingestMetrics, "ingestMetrics");
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
final String encoding = request.getHeader(HttpHeaders.CONTENT_ENCODING);
if (encoding == null || encoding.isBlank() || IDENTITY.equalsIgnoreCase(encoding.trim())) {
filterChain.doFilter(request, response);
return;
}
if (!GZIP.equalsIgnoreCase(encoding.trim())) {
// Only gzip is defined for OTLP/HTTP; reject anything else (incl. multi-encoding) explicitly
// rather than letting an undecoded body fail later as an opaque 400.
logger.warn("OTLP/HTTP trace request rejected. Unsupported Content-Encoding={}", encoding);
ingestMetrics.requestRejected(OtlpTraceIngestMetrics.Transport.HTTP, OtlpTraceIngestMetrics.RequestRejectReason.UNSUPPORTED_ENCODING);
response.setStatus(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
return;
}
filterChain.doFilter(new GzipRequestWrapper(request, maxDecompressedBytes), response);
}
/**
* Presents a gzip-encoded request as its decompressed body. Content-Length now describes the
* compressed size, so it is cleared (reported as unknown) to stop a downstream reader from
* truncating the inflated stream at the compressed length.
*/
private static final class GzipRequestWrapper extends HttpServletRequestWrapper {
private final int limit;
// Created lazily and cached so repeated getInputStream() calls return the same instance
// (servlet wrapper contract). A second GZIPInputStream over the already-consumed underlying
// stream would otherwise fail to re-read the gzip header. Single-threaded per request.View on GitHub (pinned to 744c3d3075)
Solutions
- Set the OTLP exporter's compression to gzip (OTEL_EXPORTER_OTLP_COMPRESSION=gzip or the SDK's compression option).
- Remove any Content-Encoding header injection by intermediate proxies/load balancers.
- Send the request uncompressed (no Content-Encoding) if compression is not needed — the filter passes it through.
- If using a custom client, do not send multiple encodings; gzip alone is accepted.
Example fix
// before
OtlpHttpTraceExporter.builder()
.setCompression("deflate")
.build();
// after
OtlpHttpTraceExporter.builder()
.setCompression("gzip")
.build(); Defensive patterns
Strategy: validation
Validate before calling
// client-side, before sending
String enc = request.getHeader("Content-Encoding");
boolean ok = enc == null || "gzip".equalsIgnoreCase(enc.trim());
if (!ok) {
throw new IllegalStateException("OTLP/HTTP allows only gzip Content-Encoding, got: " + enc);
} Prevention
- Set OTEL_EXPORTER_OTLP_COMPRESSION=gzip explicitly rather than relying on defaults.
- Never let an HTTP proxy add or rewrite Content-Encoding on OTLP endpoints.
- Expect HTTP 415 from the collector when encoding is wrong; treat it as a client config bug, not transient.
When it happens
Trigger: Sending a POST to the OTLP/HTTP trace endpoint with a Content-Encoding header other than 'gzip' (e.g. 'deflate', 'zstd', 'br', 'gzip, deflate', or 'identity' while actually compressing).
Common situations: Client SDK configured with a non-default compression (zstd/deflate), an HTTP proxy or gateway adding its own Content-Encoding on top, or a client compressing with 'identity' set. Often surfaces after upgrading an SDK where compression defaulted to none before.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- OTLP/HTTP decompressed request body exceeded max size: limit
- OtlpTraceParseException (syntax error, message built from sy
- OtlpTraceParseException (message from e.getMessage())
- OTLP/HTTP request body exceeded max size: limit=${limit}
- OTLP/HTTP trace request rejected. status={}, reason={}, {}
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/e85092fd071c3620.
Report an issue: GitHub.