hyperledger/fabric · error
failed to marshal request envelope: proto: Marshal called wi
Error message
failed to marshal request envelope: proto: Marshal called with nil
What it means
BFTChain.submit marshals the request envelope with proto.Marshal after a nil check; when env is nil the smartbft implementation returns the literal message "failed to marshal request envelope: proto: Marshal called with nil". It surfaces when Order or Configure propagate a nil envelope into the chain's submit path.
Source
Thrown at orderer/consensus/smartbft/chain.go:314
go func(w *worker) {
defer wg.Done()
w.doWork()
}(workers[i])
}
wg.Wait()
}
func (c *BFTChain) pruneBadRequests() {
c.consensus.Pool.Prune(func(req []byte) error {
_, err := c.consensus.Verifier.VerifyRequest(req)
return err
})
}
func (c *BFTChain) submit(env *cb.Envelope) error {
if env == nil {
return errors.New("failed to marshal request envelope: proto: Marshal called with nil")
}
reqBytes, err := proto.Marshal(env)
if err != nil {
return errors.Wrapf(err, "failed to marshal request envelope")
}
c.Logger.Debugf("Consensus.SubmitRequest, node id %d", c.Config.SelfID)
if err = c.consensus.SubmitRequest(reqBytes); err != nil {
return errors.Wrapf(err, "failed to submit request")
}
return nil
}
// Order accepts a message which has been processed at a given configSeq.
// If the configSeq advances, it is the responsibility of the consenter
// to revalidate and potentially discard the message
// The consenter may return an error, indicating the message was not accepted
func (c *BFTChain) Order(env *cb.Envelope, configSeq uint64) error {View on GitHub (pinned to 2736b63f8f)
Solutions
- Guard the call site: never pass a nil envelope to Order/Configure; return early when envelope construction fails
- Check errors from upstream envelope creation (e.g. protoutil.Marshal/Filter results) before calling Order
- Fix the producer that returned nil instead of a valid cb.Envelope or a proper error
Example fix
// before
env, err := buildEnvelope(msg)
// err ignored, env may be nil
c.Order(env)
// after
env, err := buildEnvelope(msg)
if err != nil {
return errors.Wrap(err, "failed to build envelope")
}
if env == nil {
return errors.New("nil envelope")
}
c.Order(env) Defensive patterns
Strategy: try-catch
Validate before calling
if env == nil {
return errors.New("cannot submit nil envelope")
} Try / catch
defer func() {
if r := recover(); r != nil { /* handle nil envelope path */ }
}()
if env == nil {
return errors.New("failed to marshal request envelope: proto: Marshal called with nil")
}
if err := chain.Order(env); err != nil {
return errors.Wrap(err, "submit failed")
} Prevention
- Always check the error from envelope construction before calling Order/Configure
- Return early on upstream errors instead of passing zero-value envelopes
- Add unit tests asserting Order/Configure reject nil envelopes explicitly
When it happens
Trigger: Calling c.Order(nil) or c.Configure(nil) (or an upstream path that produced a nil *cb.Envelope) on a smartbft BFTChain.
Common situations: A filter/processor upstream returned nil envelope on error without short-circuiting; refactored code path that no longer guarantees a constructed envelope; misbehaving custom consensus/processor feeding nil into Order.
Related errors
- proto: Marshal called with nil
- failed to unmarshal BFT metadata configuration
- invalid consensus type property in config: %v
- invalid options encoded in consensus metadata: %v
- bad payload
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/dc8c6a17a8d74189.
Report an issue: GitHub.