hyperledger/fabric · error

nil envelope payload

Error message

nil envelope payload

What it means

validateProtoAndConstructTxEnv checks that the envelope's Payload bytes are present before unmarshalling. An empty payload means the envelope was signed/sent without a payload, so it cannot be parsed; it returns BAD_PAYLOAD. This is a defensive nil/empty check preceding protoutil.UnmarshalPayload.

Source

Thrown at core/tx/processor_factory.go:56

		}
	}
	return c.NewProcessor(txEnv)
}

// validateProtoAndConstructTxEnv attempts to unmarshal the bytes and prepare an instance of struct tx.Envelope
// It returns an error of type `tx.InvalidErr` if the proto message is found to be invalid
func validateProtoAndConstructTxEnv(txEnvelopeBytes []byte) (*tx.Envelope, error) {
	txenv, err := protoutil.UnmarshalEnvelope(txEnvelopeBytes)
	if err != nil {
		return nil, &tx.InvalidErr{
			ActualErr:      err,
			ValidationCode: peer.TxValidationCode_INVALID_OTHER_REASON,
		}
	}

	if len(txenv.Payload) == 0 {
		return nil, &tx.InvalidErr{
			ActualErr:      errors.New("nil envelope payload"),
			ValidationCode: peer.TxValidationCode_BAD_PAYLOAD,
		}
	}

	payload, err := protoutil.UnmarshalPayload(txenv.Payload)
	if err != nil {
		return nil, &tx.InvalidErr{
			ActualErr:      err,
			ValidationCode: peer.TxValidationCode_BAD_PAYLOAD,
		}
	}

	if payload.Header == nil {
		return nil, &tx.InvalidErr{
			ActualErr:      errors.New("nil payload header"),
			ValidationCode: peer.TxValidationCode_BAD_PAYLOAD,
		}
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure the envelope is built via protoutil.CreateSignedEnvelope (or Marshal of a populated Payload) so Payload bytes are non-empty.
  2. Verify the source of the envelope bytes — re-marshal the full Envelope, not just header fields.
  3. Add a client-side check len(env.Payload) > 0 before dispatching.

Example fix

// before
env := &common.Envelope{Signature: sig}
// after
payloadBytes, _ := protoutil.Marshal(payload)
env := &common.Envelope{Payload: payloadBytes, Signature: sig}
Defensive patterns

Strategy: validation

Validate before calling

if len(env.Payload) == 0 { return errors.New("envelope payload is empty") }

Type guard

func hasPayload(env *common.Envelope) bool { return env != nil && len(env.Payload) > 0 }

Try / catch

// caller of CreateProcessor
_, err := f.CreateProcessor(txEnv)
var ierr *tx.InvalidErr
if errors.As(err, &ierr) && ierr.ValidationCode == peer.TxValidationCode_BAD_PAYLOAD {
    // reject/move to failed-transactions log
}

Prevention

When it happens

Trigger: Creating a common.Envelope with Payload left nil/empty, or an envelope that lost its payload during serialization/transport corruption.

Common situations: Test code signing an empty envelope; network corruption or manual byte-slicing of envelopes; replaying truncated datagrams; clients that marshaled a nil Payload message.

Related errors


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