hashicorp/consul · error
client streams are unsupported
Error message
client streams are unsupported
What it means
The protoc-gen-grpc-clone plugin panics during code generation (internal/tools/protoc-gen-grpc-clone/internal/generate/generate.go:83) when a service method declares a client stream (streaming request). The generator only implements cloning code for unary and server-streaming methods; the comment 'when we need these we can implement this' marks client streams as unimplemented. This is a build-time/codegen crash, not a runtime error: protoc exits non-zero and no Go output is produced for that run.
Source
Thrown at internal/tools/protoc-gen-grpc-clone/internal/generate/generate.go:83
filename := file.GeneratedFilenamePrefix + "_cloning_grpc.pb.go"
genFile := g.p.NewGeneratedFile(filename, file.GoImportPath)
for _, svc := range file.Services {
svcTypes := &cloningServiceTypes{
ClientTypeName: genFile.QualifiedGoIdent(protogen.GoIdent{GoName: svc.GoName + "Client", GoImportPath: file.GoImportPath}),
ServerTypeName: genFile.QualifiedGoIdent(protogen.GoIdent{GoName: svc.GoName + "Server", GoImportPath: file.GoImportPath}),
CloningClientTypeName: genFile.QualifiedGoIdent(protogen.GoIdent{GoName: "Cloning" + svc.GoName + "Client", GoImportPath: file.GoImportPath}),
ServiceName: svc.GoName,
}
tsvc := cloningService{
cloningServiceTypes: svcTypes,
}
for _, method := range svc.Methods {
if method.Desc.IsStreamingClient() {
// when we need these we can implement this
panic("client streams are unsupported")
}
if method.Desc.IsStreamingServer() {
tsvc.ServerStreamMethods = append(tsvc.ServerStreamMethods, &inmemMethod{
cloningServiceTypes: svcTypes,
Method: method,
})
// record that we need to also generate the inmem stream client code
// into this directory
g.directories[filepath.Dir(filename)] = pkgInfo{impPath: file.GoImportPath, pkgName: file.GoPackageName}
} else {
tsvc.UnaryMethods = append(tsvc.UnaryMethods, &inmemMethod{
cloningServiceTypes: svcTypes,
Method: method,
})
}
}View on GitHub (pinned to 2397ff0d76)
Solutions
- Redesign the RPC to be unary or server-streaming (server streams ARE supported and generate inmem stream client code)
- Move the streaming service into a separate .proto file that is excluded from grpc-clone generation
- If the stream is genuinely required, implement client-stream support in the generator (extend inmemMethod for request streams)
- Add a pre-generation lint that greps protos for 'stream' in the request position so CI fails with a clear message instead of a protoc panic
Example fix
// before (proto)
service Metrics {
rpc Export (stream Payload) returns (Ack); // client stream -> plugin panics
}
// after (proto)
service Metrics {
rpc Export (Payload) returns (Ack); // unary: supported
rpc Watch (Req) returns (stream Resp); // server stream: supported
} Defensive patterns
Strategy: validation
Validate before calling
#!/bin/sh # fail before protoc runs if any request position uses 'stream' if grep -rnE 'rpc +[A-Za-z0-9_]+ *\( *stream' proto/ ; then echo "client-streaming RPCs are unsupported by protoc-gen-grpc-clone" >&2 exit 1 fi protoc --plugin=protoc-gen-grpc-clone ...
Try / catch
// in the plugin's main, turn the panic into a clean codegen failure
defer func() {
if r := recover(); r != nil {
fmt.Fprintf(os.Stderr, "protoc-gen-grpc-clone: %v\n", r)
os.Exit(1)
}
}() Prevention
- Keep streaming methods out of protos processed by grpc-clone, or gate them behind a lint in CI
- Remember server streams are supported; only the request (client) side panics
- When copying protos from other projects, audit method shapes before wiring them into generation
When it happens
Trigger: Running proto generation (make proto / protoc with --go-grpc-clone or equivalent plugin invocation) on a .proto containing 'rpc Foo (stream Req) returns (Resp)' or a bidi 'rpc Chat (stream A) returns (stream B)'.
Common situations: Adding a client-streaming or bidi-streaming RPC to a proto covered by the grpc-clone generator in the Consul repo; copying an external proto with streaming methods into the generation path; upgrading protoc toolchains without checking method shapes.
Related errors
- unable to convert ConfigEntry of kind %s to structs
- unable to convert %T to proto
- ClusterSize not set
- failed to decode request: %v
- failed to decode batch updates: %v
AI-assisted analysis of hashicorp/consul@2397ff0d76 (2026-08-15).
Data as JSON: /api/errors/70858839a86e5937.
Report an issue: GitHub.