{"record":{"id":"e333cd5c626f50a5","repo":"grpc/grpc-go","slug":"external-processor-unexpectedly-sent-response-trai","errorCode":null,"errorMessage":"external processor unexpectedly sent response trailers when response trailer processing is disabled","messagePattern":"external processor unexpectedly sent response trailers when response trailer processing is disabled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/httpfilter/extproc/ext_proc.go","lineNumber":1333,"sourceCode":"\t\t\theader := resp.GetResponseHeaders()\n\t\t\t// Check if the status in the header response is CONTINUE; if not, fail\n\t\t\t// the stream.\n\t\t\tif status := header.GetResponse().GetStatus(); status != v3procservicepb.CommonResponse_CONTINUE {\n\t\t\t\tcs.failProcStream(fmt.Errorf(\"external processor returned unexpected status %v for response headers, expected %v\", status, v3procservicepb.CommonResponse_CONTINUE))\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif err = cs.applyMutations(header.GetResponse().GetHeaderMutation(), cs.responseHeader); err != nil {\n\t\t\t\tcs.failProcStream(err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// Signal that the response header is modified and ready to be sent to the\n\t\t\t// client, so that if there is any buffered response body, it can be sent\n\t\t\t// after the header.\n\t\t\tcs.fireResponseHeadersReady()\n\n\t\tcase resp.GetResponseTrailers() != nil:\n\t\t\tif cs.config.processingModes.responseTrailerMode == modeSkip {\n\t\t\t\tcs.failProcStream(fmt.Errorf(\"external processor unexpectedly sent response trailers when response trailer processing is disabled\"))\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif !cs.trailerSent.Load() {\n\t\t\t\tcs.failProcStream(fmt.Errorf(\"external processor sent response trailers before response trailers were sent to it\"))\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif cs.responseTrailerReady.HasFired() {\n\t\t\t\tcs.failProcStream(fmt.Errorf(\"external processor unexpectedly sent duplicate response trailers after response trailers were already processed\"))\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttrailer := resp.GetResponseTrailers()\n\t\t\tif err = cs.applyMutations(trailer.GetHeaderMutation(), cs.responseTrailers); err != nil {\n\t\t\t\tcs.failProcStream(err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// Signal that the response trailer is modified and ready to be sent to\n\t\t\t// the client.\n\t\t\tcs.fireResponseTrailerReady()","sourceCodeStart":1315,"sourceCodeEnd":1351,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/xds/httpfilter/extproc/ext_proc.go#L1315-L1351","documentation":"Raised when the server sends response_trailers while responseTrailerMode is modeSkip. The client did not negotiate response-trailer processing, so a response-trailers message is a protocol violation and the proc stream is failed.","triggerScenarios":"processing_mode.response_trailer_mode == SKIP and the server emits a ProcessingResponse.response_trailers.","commonSituations":"Server always mutates trailers; client left response_trailer_mode at SKIP (the default when not using GRPC body mode). Per-route override disabled trailers but shared server still emits them.","solutions":["Set processing_mode.response_trailer_mode to SEND if trailer processing is desired.","Otherwise fix the server to not emit response_trailers when trailers are not negotiated.","Enable failure_mode_allow to bypass during remediation."],"exampleFix":"// before\nprocessing_mode:\n  response_trailer_mode: SKIP   # server sends response_trailers anyway\n\n// after\nprocessing_mode:\n  response_trailer_mode: SEND","handlingStrategy":"validation","validationCode":"// Server: suppress response_trailers when negotiated trailer mode is SKIP.\nfunc maybeResponseTrailers(mode v3procfilterpb.ProcessingMode_HeaderSendMode, resp *pb.ProcessingResponse) *pb.ProcessingResponse {\n    if mode == v3procfilterpb.ProcessingMode_SKIP && resp.GetResponseTrailers() != nil {\n        return nil\n    }\n    return resp\n}","typeGuard":null,"tryCatchPattern":"// Client: failure_mode_allow -> bypass.","preventionTips":["Set response_trailer_mode SEND iff the server will mutate trailers.","Enable failure_mode_allow during server rollouts."],"tags":["extproc","protocol-violation","processing-mode","response-trailers","server-bug"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}