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

  1. Redesign the RPC to be unary or server-streaming (server streams ARE supported and generate inmem stream client code)
  2. Move the streaming service into a separate .proto file that is excluded from grpc-clone generation
  3. If the stream is genuinely required, implement client-stream support in the generator (extend inmemMethod for request streams)
  4. 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

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


AI-assisted analysis of hashicorp/consul@2397ff0d76 (2026-08-15). Data as JSON: /api/errors/70858839a86e5937. Report an issue: GitHub.