hyperledger/fabric · error
receiver %T.%s does not accept a proto.Message as its argume
Error message
receiver %T.%s does not accept a proto.Message as its argument, it is '%T'
What it means
Dispatch uses reflection to invoke a chaincode-receiver method whose input argument must implement proto.Message. After creating a new instance of the declared input type, it asserts that instance to proto.Message; if the assertion fails the method's input type is not a valid protobuf message, so the call cannot be dispatched.
Source
Thrown at core/dispatcher/dispatcher.go:58
return nil, errors.Errorf("receiver %T.%s does not accept a pointer as its argument", receiver, methodName)
}
if method.Type().NumOut() != 2 {
return nil, errors.Errorf("receiver %T.%s returns %d values but expected 2", receiver, methodName, method.Type().NumOut())
}
if !method.Type().Out(0).Implements(reflect.TypeFor[proto.Message]()) {
return nil, errors.Errorf("receiver %T.%s does not return a an implementor of proto.Message as its first return value", receiver, methodName)
}
if !method.Type().Out(1).Implements(reflect.TypeFor[error]()) {
return nil, errors.Errorf("receiver %T.%s does not return an error as its second return value", receiver, methodName)
}
inputValue := reflect.New(inputType.Elem())
inputMsg, ok := inputValue.Interface().(proto.Message)
if !ok {
return nil, errors.Errorf("receiver %T.%s does not accept a proto.Message as its argument, it is '%T'", receiver, methodName, inputValue.Interface())
}
err := d.Protobuf.Unmarshal(inputBytes, inputMsg)
if err != nil {
return nil, errors.WithMessagef(err, "could not decode input arg for %T.%s", receiver, methodName)
}
outputVals := method.Call([]reflect.Value{inputValue})
if !outputVals[1].IsNil() {
return nil, outputVals[1].Interface().(error)
}
if outputVals[0].IsNil() {
return nil, errors.Errorf("receiver %T.%s returned (nil, nil) which is not allowed", receiver, methodName)
}
outputMsg := outputVals[0].Interface().(proto.Message)View on GitHub (pinned to 2736b63f8f)
Solutions
- Change the receiver method's input type to a generated protobuf message type that implements proto.Message
- Regenerate protobuf code with protoc-gen-go so the struct implements the proto.Message interface (ProtoReflect method)
- Ensure only one protobuf module version is imported so the interface assertion succeeds
Example fix
// before func (r *Receiver) DoThing(ctx context.Context, in *MyPlainStruct) (proto.Message, error) // after func (r *Receiver) DoThing(ctx context.Context, in *pb.MyThingRequest) (proto.Message, error)
Defensive patterns
Strategy: validation
Validate before calling
var _ proto.Message = (*pb.MyThingRequest)(nil) // compile-time check before registering
func validInput(m interface{}) bool {
_, ok := m.(proto.Message)
return ok
} Type guard
func isProtoMessage(v interface{}) bool {
_, ok := v.(proto.Message)
return ok
} Prevention
- Add compile-time interface assertions (var _ proto.Message = (*T)(nil)) for all receiver input types
- Use protoc-gen-go to generate all message types; never hand-roll them
- Pin a single protobuf module version across the project
When it happens
Trigger: Registering/invoke-dispatching to a receiver method whose input parameter is a Go struct that does not embed/implement proto.Message (e.g. a plain struct or pointer-to-wrong-type), then calling Invoke on it.
Common situations: Hand-written chaincode receivers using custom argument structs instead of generated protobuf types; proto package version mismatches (google.golang.org/protobuf vs github.com/golang/protobuf) so the type no longer satisfies proto.Message; typos in generated code regeneration.
Related errors
- receiver %T.%s returned (nil, nil) which is not allowed
- message of type %s unknown
- failed to unmarshal response for transaction %s
- unmarshal failed
- unknown operation type
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/6be4bc150f4ba9aa.
Report an issue: GitHub.