{"record":{"id":"ed96dfa5d394a5c2","repo":"pinpoint-apm/pinpoint","slug":"otlp-http-trace-request-rejected-status-reaso","errorCode":null,"errorMessage":"OTLP/HTTP trace request rejected. status={}, reason={}, {}","messagePattern":"OTLP/HTTP trace request rejected\\. status=(.+?), reason=(.+?), (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"otlptrace/otlptrace-collector/src/main/java/com/navercorp/pinpoint/otlp/trace/collector/controller/OtlpTraceHttpAdmissionFilter.java","lineNumber":144,"sourceCode":"                effectiveRequest = limited;\n            }\n            filterChain.doFilter(effectiveRequest, response);\n        } finally {\n            if (limited != null) {\n                ingestMetrics.requestBytes(OtlpTraceIngestMetrics.Transport.HTTP, limited.bytesRead());\n            }\n            admissionBytes.release(reserveBytes);\n            concurrency.release();\n        }\n    }\n\n    private void reject(HttpServletResponse response, int status, boolean retryable, RequestRejectReason reason, String detail) {\n        if (retryable) {\n            response.setHeader(\"Retry-After\", Integer.toString(retryAfterSeconds));\n        }\n        response.setStatus(status);\n        ingestMetrics.requestRejected(OtlpTraceIngestMetrics.Transport.HTTP, reason);\n        logger.warn(\"OTLP/HTTP trace request rejected. status={}, reason={}, {}\", status, reason.tagValue(), detail);\n    }\n\n    /**\n     * Wraps the request so an unknown-length (chunked) body is read through a size-limited stream.\n     */\n    private static final class LimitedRequestWrapper extends HttpServletRequestWrapper {\n        private final long limit;\n        private LimitedServletInputStream stream;\n\n        private LimitedRequestWrapper(HttpServletRequest request, long limit) {\n            super(request);\n            this.limit = limit;\n        }\n\n        @Override\n        public ServletInputStream getInputStream() throws IOException {\n            if (stream == null) {\n                stream = new LimitedServletInputStream(super.getInputStream(), limit);","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/pinpoint-apm/pinpoint/blob/744c3d3075e595656abb1ae331ad2c0e4c9eb996/otlptrace/otlptrace-collector/src/main/java/com/navercorp/pinpoint/otlp/trace/collector/controller/OtlpTraceHttpAdmissionFilter.java#L126-L162","documentation":"OtlpTraceHttpAdmissionFilter.reject is the central admission-control rejection path: when an OTLP/HTTP trace request fails admission (size limits, oversized/chunked body, rate/byte budget), the filter writes an HTTP status (with a Retry-After header when the rejection is retryable), records a RequestRejectReason in ingest metrics, and logs 'OTLP/HTTP trace request rejected. status={}, reason={}, {}'. It protects the collector from oversized or excessive requests.","triggerScenarios":"A request body exceeding the configured max decompressed/accepted size, an unknown-length chunked body too large for the LimitedRequestWrapper, or other admission policy checks in doFilterInternal calling reject() with the corresponding status and RequestRejectReason.","commonSituations":"Burst traffic from many OTel SDK instances, a batch processor producing very large export payloads, clients ignoring Retry-After on 429/503 responses and hammering the endpoint, or gateway-buffered chunked uploads hitting size limits.","solutions":["Read the log's status/reason fields to identify which limit was hit, then lower client batch size (BatchSpanProcessor max_export_batch_size / max_queue_size).","If retryable, honor the Retry-After header and back off with jitter in the exporter/proxy.","Raise the collector's admission limits (max request/decompressed byte config) if legitimate payloads are being rejected.","Check ingest metrics for the RequestRejectReason to confirm whether it is payload size vs. load, and scale collector replicas if the latter."],"exampleFix":"// before (client)\nBatchSpanProcessor.builder(exporter)\n    .setMaxExportBatchSize(2048)\n    .build();\n\n// after\nBatchSpanProcessor.builder(exporter)\n    .setMaxExportBatchSize(512)\n    .build();","handlingStrategy":"retry","validationCode":"// client-side: cap payload before sending\nif (estimatedBodyBytes > maxAcceptedBytes) {\n    splitBatch(); // export in smaller chunks\n}","typeGuard":null,"tryCatchPattern":"// retry only when the rejection is retryable and honor Retry-After\nif (status == 429 || status == 503) {\n    long waitMs = retryAfterHeader != null ? Long.parseLong(retryAfterHeader) * 1000L : backoffMs;\n    Thread.sleep(waitMs + jitter());\n    retryExport();\n}","preventionTips":["Keep export batch sizes small and bounded.","Honor Retry-After; never hammer the admission filter in a tight retry loop.","Monitor collector reject metrics to size limits and capacity proactively."],"tags":["http","otlp","admission-control","rate-limit"],"backgroundTag":"rate-limit-exceeded","analyzedSha":"744c3d3075e595656abb1ae331ad2c0e4c9eb996","analyzedAt":"2026-09-07T18:48:45.289Z","contentChangedAt":"2026-09-07T18:48:45.289Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}