hyperledger/fabric · error
receiver %T.%s returned (nil, nil) which is not allowed
Error message
receiver %T.%s returned (nil, nil) which is not allowed
What it means
After invoking the receiver method, Dispatch requires the first return value (the output proto.Message) to be non-nil when the error return is nil. A receiver returning (nil, nil) gives the dispatcher nothing to marshal, so it is rejected as a programming error.
Source
Thrown at core/dispatcher/dispatcher.go:73
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)
resultBytes, err := d.Protobuf.Marshal(outputMsg)
if err != nil {
return nil, errors.WithMessagef(err, "failed to marshal result for %T.%s", receiver, methodName)
}
return resultBytes, nil
}
View on GitHub (pinned to 2736b63f8f)
Solutions
- Return a valid (non-nil) proto.Message from the receiver on success paths
- If no payload is expected, return an empty message instance (e.g. &pb.EmptyResponse{}) instead of nil
- Return a non-nil error instead of nil,nil for the no-result case
Example fix
// before
func (r *Receiver) DoThing(ctx context.Context, in *pb.Req) (proto.Message, error) {
return nil, nil
}
// after
func (r *Receiver) DoThing(ctx context.Context, in *pb.Req) (proto.Message, error) {
return &pb.EmptyResponse{}, nil
} Defensive patterns
Strategy: type-guard
Validate before calling
// receiver-side unit test
out, err := recv.DoThing(ctx, req)
if err == nil && out == nil { t.Fatal("receiver returned (nil, nil)") } Type guard
func isNilProto(m proto.Message) bool {
return m == nil || !m.ProtoReflect().IsValid()
} Prevention
- Never `return nil, nil` from receiver methods; return an empty message or an error
- Lint receivers with a wrapper test invoking each method and asserting non-nil output on success
- Model optional responses as explicit empty message types
When it happens
Trigger: A receiver method invoked via Invoke/Dispatch returns (nil, nil) — e.g. it does `return nil, nil` on a success path or forgets to set its response message.
Common situations: Chaincode handler that returns early without building a response proto; methods with optional responses that were written as plain Go functions returning nil.
Related errors
- receiver %T.%s does not accept a proto.Message as its argume
- 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/7aa169437de04026.
Report an issue: GitHub.