{"record":{"id":"15e1df0984bbb160","repo":"apache/shenyu","slug":"unable-to-merge-from-the-supplied-input-stream","errorCode":null,"errorMessage":"Unable to merge from the supplied input stream","messagePattern":"Unable to merge from the supplied input stream","errorType":"exception","errorClass":"ShenyuGrpcException","httpStatus":null,"severity":"error","filePath":"shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/proto/DynamicMessageMarshaller.java","lineNumber":47,"sourceCode":"/**\n * Dynamic messages.\n */\npublic class DynamicMessageMarshaller implements Marshaller<DynamicMessage> {\n\n    private final Descriptor messageDescriptor;\n\n    public DynamicMessageMarshaller(final Descriptor messageDescriptor) {\n        this.messageDescriptor = messageDescriptor;\n    }\n\n    @Override\n    public DynamicMessage parse(final InputStream inputStream) {\n        try {\n            return DynamicMessage.newBuilder(messageDescriptor)\n                    .mergeFrom(inputStream, ExtensionRegistryLite.getEmptyRegistry())\n                    .build();\n        } catch (IOException e) {\n            throw new ShenyuGrpcException(\"Unable to merge from the supplied input stream\", e);\n        }\n    }\n\n    @Override\n    public InputStream stream(final DynamicMessage abstractMessage) {\n        return abstractMessage.toByteString().newInput();\n    }\n}\n","sourceCodeStart":29,"sourceCodeEnd":56,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/proto/DynamicMessageMarshaller.java#L29-L56","documentation":"DynamicMessageMarshaller.parse deserializes a gRPC response into a DynamicMessage using the descriptor derived from proto metadata. If reading/merging the InputStream throws IOException (truncated body, connection reset, corrupt bytes), it is wrapped in ShenyuGrpcException 'Unable to merge from the supplied input stream'.","triggerScenarios":"parse() is invoked during response deserialization and mergeFrom(inputStream, ...) throws IOException — typically a broken/truncated stream from the upstream gRPC call.","commonSituations":"Upstream closes the connection mid-response; response bytes don't match the expected proto message descriptor (wrong method metadata in ShenYu rule); proxy/network devices cutting long-lived gRPC streams.","solutions":["Verify the proto descriptor used by the plugin matches the backend's actual response message (check the rpcExt/metadata for the method).","Check gateway-to-backend network stability; look for connection resets or proxy timeouts.","Retry the request; a transient stream truncation may succeed on retry.","Capture backend logs for the request to confirm the server sent a complete, well-formed response."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    return grpcCall(request);\n} catch (ShenyuGrpcException e) {\n    if (isTransient(e) && attempt < MAX_RETRIES) {\n        return retry(attempt + 1);\n    }\n    throw e;\n}","preventionTips":["Ensure rpcExt metadata declares the correct response message type for each method.","Enable keepalive/idle timeouts to avoid mid-stream connection drops.","Check intermediary proxies/LBs for gRPC stream timeout settings.","Alert on repeated 'Unable to merge' errors — they usually indicate descriptor mismatch or truncation."],"tags":["grpc","protobuf","deserialization","io"],"backgroundTag":"protobuf-unmarshal-failed","analyzedSha":"567142e07261b3e615ae8850b30f4421f455cc5d","analyzedAt":"2026-09-12T10:08:21.293Z","contentChangedAt":"2026-09-12T10:08:21.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}