{"record":{"id":"f94fb82e6427029b","repo":"hyperledger/fabric","slug":"message-is-neither-a-submit-nor-consensus-request","errorCode":null,"errorMessage":"Message is neither a Submit nor Consensus request","messagePattern":"Message is neither a Submit nor Consensus request","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/common/cluster/clusterservice.go","lineNumber":226,"sourceCode":"\n\texp.checkExpiration(time.Now(), channel)\n\n\tif tranReq := request.GetNodeTranrequest(); tranReq != nil {\n\t\tsubmitReq := &orderer.SubmitRequest{\n\t\t\tChannel:           channel,\n\t\t\tLastValidationSeq: tranReq.LastValidationSeq,\n\t\t\tPayload:           tranReq.Payload,\n\t\t}\n\t\treturn s.RequestHandler.OnSubmit(channel, sender, submitReq)\n\t} else if clusterConReq := request.GetNodeConrequest(); clusterConReq != nil {\n\t\tconReq := &orderer.ConsensusRequest{\n\t\t\tChannel:  channel,\n\t\t\tPayload:  clusterConReq.Payload,\n\t\t\tMetadata: clusterConReq.Metadata,\n\t\t}\n\t\treturn s.RequestHandler.OnConsensus(channel, sender, conReq)\n\t}\n\treturn errors.Errorf(\"Message is neither a Submit nor Consensus request\")\n}\n\nfunc (s *ClusterService) initializeExpirationCheck(stream orderer.ClusterNodeService_StepServer, endpoint, nodeName string) *certificateExpirationCheck {\n\texpiresAt := time.Time{}\n\tcert := util.ExtractCertificateFromContext(stream.Context())\n\tif cert != nil {\n\t\texpiresAt = cert.NotAfter\n\t}\n\n\treturn &certificateExpirationCheck{\n\t\tminimumExpirationWarningInterval: s.MinimumExpirationWarningInterval,\n\t\texpirationWarningThreshold:       s.CertExpWarningThreshold,\n\t\texpiresAt:                        expiresAt,\n\t\tendpoint:                         endpoint,\n\t\tnodeName:                         nodeName,\n\t\talert: func(template string, args ...any) {\n\t\t\ts.Logger.Warningf(template, args...)\n\t\t},","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/common/cluster/clusterservice.go#L208-L244","documentation":"handleMessage inspects the received clusterRequest's Type. Valid requests are either a Submit request (forwarded to RequestHandler.OnSubmit) or a Consensus request (forwarded to RequestHandler.OnConsensus). Any other message type reaching this point is a protocol violation — the auth envelope carried a message the cluster Step service cannot dispatch — so the stream errors with 'Message is neither a Submit nor Consensus request'.","triggerScenarios":"A Step message arrives whose inner clusterRequest type is neither Submit nor Consensus — e.g. a client sends a mis-constructed orderer.StepRequest, an envelope's payload was wrapped/typed incorrectly, or a version-skewed node sends a type this build doesn't recognize.","commonSituations":"Mixed Fabric versions where the wire format or request types changed; a custom/gRPC client hand-crafting Step messages; corrupted or re-wrapped envelopes produced by intermediate proxies; a sender accidentally using the peer-facing broadcast/deliver payload format against the orderer cluster port.","solutions":["Align all orderers on the same Fabric version so the Step request types are understood on both ends.","On the sending side, ensure only cluster.Step requests built via the cluster RPC (Submit via Broadcast-style forwarding, Consensus via etcdraft) are sent to the cluster port — not Deliver/Broadcast envelopes.","Inspect the incoming message with StepLogger debug to identify the unexpected Type and which sender produced it.","Check for intermediaries or custom code that re-wraps or re-marshals the StepRequest payload and remove that behavior.","If a custom client is at fault, regenerate the request using the fabric-protos orderer.ClusterNodeService definitions."],"exampleFix":"// before (custom client sends a Broadcast envelope to the cluster Step endpoint)\nreq := &orderer.BroadcastRequest{...}\nstepClient.Send(req)\n// after — send the proper cluster request type\nreq := &orderer.StepRequest{\n    Payload: &orderer.StepRequest_SubmitRequest{SubmitRequest: submitReq},\n}\nstepClient.Send(req)","handlingStrategy":"validation","validationCode":"// Before dialing the cluster port, assert the request type is dispatchable\nswitch r := stepReq.Payload.(type) {\ncase *orderer.StepRequest_SubmitRequest:\n    // ok\ncase *orderer.StepRequest_ConsensusRequest:\n    // ok\ndefault:\n    return fmt.Errorf(\"refusing to send unsupported StepRequest payload %T over cluster port\", r)\n}","typeGuard":"func isDispatchableStepRequest(p *orderer.StepRequest) bool {\n    switch p.Payload.(type) {\n    case *orderer.StepRequest_SubmitRequest, *orderer.StepRequest_ConsensusRequest:\n        return true\n    }\n    return false\n}","tryCatchPattern":"if err := handleMessage(...); err != nil && strings.Contains(err.Error(), \"neither a Submit nor Consensus\") {\n    log.Printf(\"unsupported cluster message from %s; dropping stream\", addr)\n    stream.CloseSend()\n}","preventionTips":["Use the same fabric-protos version to build Step requests on both ends","Point Broadcast/Deliver clients at the standard ports, never at the cluster Step port","Audit any custom gRPC intermediaries for payload re-marshaling","Run a two-node test channel after upgrading Fabric versions before a production rollout"],"tags":["hyperledger-fabric","orderer","grpc","protocol"],"backgroundTag":"unsupported-message-type","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}