hyperledger/fabric · error

bad payload

Error message

bad payload

What it means

ValidateUpdateConfigEnvelope parses the payload of an envelope submitted to the channel participation API and returns this error when protoutil.UnmarshalPayload fails, i.e. the envelope's Payload bytes cannot be decoded into a common.Payload protobuf. It signals the submitted envelope is malformed at the outermost level, before any header or channel checks can run.

Source

Thrown at orderer/common/channelparticipation/validator.go:76

	}

	_, isAppChannel := bundle.ApplicationConfig()
	if !isAppChannel {
		return "", errors.New("invalid config: must contain application config")
	}

	return channelID, err
}

// ValidateUpdateConfigEnvelope checks whether this envelope can be used as an update config for the channel participation API.
// It returns the channel ID.
// It verifies that it is not a system channel by checking that consortiums config does not exist.
// It verifies it is an application channel by checking that the application group exists.
// It returns an error when it cannot be used as a update config envelope.
func ValidateUpdateConfigEnvelope(env *cb.Envelope) (channelID string, err error) {
	payload, err := protoutil.UnmarshalPayload(env.Payload)
	if err != nil {
		return "", errors.New("bad payload")
	}

	if payload.Header == nil || payload.Header.ChannelHeader == nil {
		return "", errors.New("bad header")
	}

	ch, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)
	if err != nil {
		return "", errors.New("could not unmarshall channel header")
	}

	if ch.Type != int32(cb.HeaderType_CONFIG_UPDATE) {
		return "", errors.New("bad type")
	}

	if ch.ChannelId == "" {
		return "", errors.New("empty channel id")
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Regenerate the envelope with a correct marshaled payload: build common.Payload, call protoutil.Marshal (or CreateSignedEnvelope) rather than assembling structs manually.
  2. Verify the payload bytes decode: run protoutil.UnmarshalPayload on them locally before submitting.
  3. Check that the client SDK/tool version producing the envelope matches the orderer's Fabric version.
  4. Inspect the submitted file/binary for truncation or accidental editing (base64 vs raw bytes confusion).

Example fix

// before
env := &cb.Envelope{Payload: payloadBytes} // payloadBytes is JSON or nil
// after
payload := &cb.Payload{Header: hdr, Data: configUpdateBytes}
payloadBytes, _ := protoutil.Marshal(payload)
env := &cb.Envelope{Payload: payloadBytes, Signature: sig}
Defensive patterns

Strategy: validation

Validate before calling

if env == nil || len(env.Payload) == 0 { return errors.New("envelope payload is empty") }
if _, err := protoutil.UnmarshalPayload(env.Payload); err != nil {
    return fmt.Errorf("payload is not a valid protobuf: %w", err)
}

Type guard

func hasValidPayload(env *cb.Envelope) bool {
    if env == nil || len(env.Payload) == 0 { return false }
    _, err := protoutil.UnmarshalPayload(env.Payload)
    return err == nil
}

Try / catch

_, err := channelparticipation.ValidateUpdateConfigEnvelope(env)
if err != nil {
    if strings.Contains(err.Error(), "bad payload") {
        // regenerate envelope with a properly marshaled payload
    }
    return err
}

Prevention

When it happens

Trigger: Calling the channel participation REST/CLI update endpoint with an envelope whose Payload field is nil, empty, or not a serialized protobuf (e.g. constructing cb.Envelope by hand and forgetting to marshal the payload, or sending a corrupted/truncated payload).

Common situations: Scripts generating config-update envelopes incorrectly; tools writing raw JSON into the envelope payload field instead of base64 marshaled protobuf; version mismatch where payload encoding differs between client SDK and orderer; files truncated or hand-edited before joining a channel.

Related errors


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