hyperledger/fabric · error

failed to marshal request envelope

Error message

failed to marshal request envelope

What it means

This error is returned by BFTChain.submit when the incoming *cb.Envelope cannot be serialized with proto.Marshal, or (defensively) when the envelope itself is nil. The ordering node cannot hand a request to the SmartBFT consensus engine without its protobuf bytes, so submission is aborted. It wraps the underlying protobuf error via pkg/errors.Wrapf.

Source

Thrown at orderer/consensus/smartbft/chain.go:318

	}

	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 {
	seq := c.support.Sequence()
	if configSeq < seq {
		c.Logger.Warnf("Normal message was validated against %d, although current config seq has advanced (%d)", configSeq, seq)
		if _, err := c.support.ProcessNormalMsg(env); err != nil {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure the envelope passed to Order/Configure is non-nil before submitting
  2. Validate the Envelope (Payload and Signature present and valid base64/bytes) on the client before broadcast
  3. Check the wrapped proto error text (proto: Marshal called with nil) to identify which nested field is nil
  4. Rebuild/serialize the envelope client-side with protoutil.MarshalOrPanic or CreateSignedEnvelope to guarantee a well-formed message

Example fix

// before
c.Chain.Order(nil, seq) // -> failed to marshal request envelope

// after
env, err := protoutil.CreateSignedEnvelope(cb.HeaderType_ENDORSER_TRANSACTION, chID, signer, tx, 0, 0)
if err != nil { return err }
if env == nil { return errors.New("nil envelope") }
return c.Chain.Order(env, seq)
Defensive patterns

Strategy: validation

Validate before calling

func validEnvelope(env *cb.Envelope) bool {
    if env == nil { return false }
    b, err := proto.Marshal(env)
    return err == nil && len(b) > 0
}
if !validEnvelope(env) { return errors.New("invalid envelope") }
return chain.Order(env, seq)

Type guard

func isEnvelope(m interface{}) (*cb.Envelope, bool) {
    env, ok := m.(*cb.Envelope)
    if !ok || env == nil { return nil, false }
    return env, true
}

Try / catch

if err := chain.Order(env, seq); err != nil {
    if strings.Contains(err.Error(), "failed to marshal request envelope") {
        return fmt.Errorf("envelope not marshalable: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling Order() or Configure() with a nil *cb.Envelope (the submit function explicitly rejects nil), or passing an envelope containing a message that fails proto.Marshal (e.g. an embedded message with an invalid field, corrupted bytes, or a struct that exceeds protobuf limits).

Common situations: A client (Broadcast stream or SendTx path) sends an empty/garbage envelope to the orderer; middleware or tests construct Envelope structs with nil Payload/Signature fields in ways that fail marshaling; version mismatch where an internal protobuf type is malformed after an upgrade.

Related errors


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