hyperledger/fabric · error
only endorser transactions can be sent with other transactio
Error message
only endorser transactions can be sent with other transactions
What it means
In Smart BFT (v3) channels, when a batch already contains other transactions, configuration-like requests cannot be mixed in. verifyRequest rejects non-ENDORSER_TRANSACTION types when noConfigAllowed is set.
Source
Thrown at orderer/consensus/smartbft/verifier.go:175
func (v *Verifier) VerifyRequest(rawRequest []byte) (types.RequestInfo, error) {
return v.verifyRequest(rawRequest, false)
}
func (v *Verifier) verifyRequest(rawRequest []byte, noConfigAllowed bool) (types.RequestInfo, error) {
req, err := v.ReqInspector.unwrapReq(rawRequest)
if err != nil {
return types.RequestInfo{}, err
}
err = v.AccessController.Evaluate([]*protoutil.SignedData{
{Identity: req.sigHdr.Creator, Data: req.envelope.Payload, Signature: req.envelope.Signature},
})
if err != nil {
return types.RequestInfo{}, errors.Wrap(err, "access denied")
}
if noConfigAllowed && req.chHdr.Type != int32(cb.HeaderType_ENDORSER_TRANSACTION) {
return types.RequestInfo{}, errors.Errorf("only endorser transactions can be sent with other transactions")
}
if req.chHdr.ChannelId != v.Channel {
return types.RequestInfo{}, errors.Errorf("request is for channel %s but expected channel %s", req.chHdr.ChannelId, v.Channel)
}
switch req.chHdr.Type {
case int32(cb.HeaderType_CONFIG):
case int32(cb.HeaderType_ORDERER_TRANSACTION):
return types.RequestInfo{}, fmt.Errorf("orderer transactions are not supported in v3")
case int32(cb.HeaderType_ENDORSER_TRANSACTION):
default:
return types.RequestInfo{}, errors.Errorf("transaction of type %s is not allowed to be included in blocks", cb.HeaderType_name[req.chHdr.Type])
}
if req.chHdr.Type == int32(cb.HeaderType_CONFIG) {
err = v.ConfigValidator.ValidateConfig(req.envelope)
if err != nil {View on GitHub (pinned to 2736b63f8f)
Solutions
- Submit config updates when they can be processed separately from endorser transactions, per the channel's batching policy
- Use the standard config-update flow so the leader sequences the config alone
- Remove any ORDERER_TRANSACTION submissions — unsupported in v3
Defensive patterns
Strategy: validation
Validate before calling
if noConfigAllowed && hdr.Type != int32(cb.HeaderType_ENDORSER_TRANSACTION) {
return errors.New("config-like requests must be sent separately")
} Type guard
func isEndorserTx(hdr *common.ChannelHeader) bool {
return hdr.Type == int32(cb.HeaderType_ENDORSER_TRANSACTION)
} Try / catch
if _, err := VerifyRequest(req); err != nil {
if strings.Contains(err.Error(), "only endorser transactions") {
// resubmit config update via its own path
}
} Prevention
- Submit config updates separately from application traffic
- Understand BFT v3 batching rules before mixing request types
- Avoid legacy orderer transaction submissions
When it happens
Trigger: A client submits a CONFIG or ORDERER_TRANSACTION envelope to the same batch/queue as regular transactions while config requests are disallowed in that context.
Common situations: Submitting channel config updates concurrently with application traffic through the request path; tooling that injects orderer transactions into a BFT v3 channel.
Related errors
- transaction of type %s is not allowed to be included in bloc
- consenter options type mismatch
- failed to unmarshal BFT metadata configuration
- invalid BFT metadata configuration
- invalid BFT consenter mapping configuration
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/586c91d6c902aa3f.
Report an issue: GitHub.