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

  1. Guard the call site: never pass a nil envelope to Order/Configure; return early when envelope construction fails
  2. Check errors from upstream envelope creation (e.g. protoutil.Marshal/Filter results) before calling Order
  3. 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

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


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/dc8c6a17a8d74189. Report an issue: GitHub.