apache/shenyu · error · ShenyuGrpcException

Unable to merge from the supplied input stream

Error message

Unable to merge from the supplied input stream

What it means

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'.

Solutions

  1. Verify the proto descriptor used by the plugin matches the backend's actual response message (check the rpcExt/metadata for the method).
  2. Check gateway-to-backend network stability; look for connection resets or proxy timeouts.
  3. Retry the request; a transient stream truncation may succeed on retry.
  4. Capture backend logs for the request to confirm the server sent a complete, well-formed response.
Defensive patterns

Strategy: retry

Try / catch

try {
    return grpcCall(request);
} catch (ShenyuGrpcException e) {
    if (isTransient(e) && attempt < MAX_RETRIES) {
        return retry(attempt + 1);
    }
    throw e;
}

Prevention

When it happens

Trigger: parse() is invoked during response deserialization and mergeFrom(inputStream, ...) throws IOException — typically a broken/truncated stream from the upstream gRPC call.

Common situations: 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.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12). Data as JSON: /api/errors/15e1df0984bbb160. Report an issue: GitHub.

Appendix: source

Thrown at shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/proto/DynamicMessageMarshaller.java:47

/**
 * Dynamic messages.
 */
public class DynamicMessageMarshaller implements Marshaller<DynamicMessage> {

    private final Descriptor messageDescriptor;

    public DynamicMessageMarshaller(final Descriptor messageDescriptor) {
        this.messageDescriptor = messageDescriptor;
    }

    @Override
    public DynamicMessage parse(final InputStream inputStream) {
        try {
            return DynamicMessage.newBuilder(messageDescriptor)
                    .mergeFrom(inputStream, ExtensionRegistryLite.getEmptyRegistry())
                    .build();
        } catch (IOException e) {
            throw new ShenyuGrpcException("Unable to merge from the supplied input stream", e);
        }
    }

    @Override
    public InputStream stream(final DynamicMessage abstractMessage) {
        return abstractMessage.toByteString().newInput();
    }
}

View on GitHub (pinned to 567142e072)