{"record":{"id":"b844472c82ab87a4","repo":"hyperledger/fabric","slug":"bad-payload","errorCode":null,"errorMessage":"bad payload","messagePattern":"bad payload","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/common/channelparticipation/validator.go","lineNumber":76,"sourceCode":"\t}\n\n\t_, isAppChannel := bundle.ApplicationConfig()\n\tif !isAppChannel {\n\t\treturn \"\", errors.New(\"invalid config: must contain application config\")\n\t}\n\n\treturn channelID, err\n}\n\n// ValidateUpdateConfigEnvelope checks whether this envelope can be used as an update config for the channel participation API.\n// It returns the channel ID.\n// It verifies that it is not a system channel by checking that consortiums config does not exist.\n// It verifies it is an application channel by checking that the application group exists.\n// It returns an error when it cannot be used as a update config envelope.\nfunc ValidateUpdateConfigEnvelope(env *cb.Envelope) (channelID string, err error) {\n\tpayload, err := protoutil.UnmarshalPayload(env.Payload)\n\tif err != nil {\n\t\treturn \"\", errors.New(\"bad payload\")\n\t}\n\n\tif payload.Header == nil || payload.Header.ChannelHeader == nil {\n\t\treturn \"\", errors.New(\"bad header\")\n\t}\n\n\tch, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)\n\tif err != nil {\n\t\treturn \"\", errors.New(\"could not unmarshall channel header\")\n\t}\n\n\tif ch.Type != int32(cb.HeaderType_CONFIG_UPDATE) {\n\t\treturn \"\", errors.New(\"bad type\")\n\t}\n\n\tif ch.ChannelId == \"\" {\n\t\treturn \"\", errors.New(\"empty channel id\")\n\t}","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/common/channelparticipation/validator.go#L58-L94","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Regenerate the envelope with a correct marshaled payload: build common.Payload, call protoutil.Marshal (or CreateSignedEnvelope) rather than assembling structs manually.","Verify the payload bytes decode: run protoutil.UnmarshalPayload on them locally before submitting.","Check that the client SDK/tool version producing the envelope matches the orderer's Fabric version.","Inspect the submitted file/binary for truncation or accidental editing (base64 vs raw bytes confusion)."],"exampleFix":"// before\nenv := &cb.Envelope{Payload: payloadBytes} // payloadBytes is JSON or nil\n// after\npayload := &cb.Payload{Header: hdr, Data: configUpdateBytes}\npayloadBytes, _ := protoutil.Marshal(payload)\nenv := &cb.Envelope{Payload: payloadBytes, Signature: sig}","handlingStrategy":"validation","validationCode":"if env == nil || len(env.Payload) == 0 { return errors.New(\"envelope payload is empty\") }\nif _, err := protoutil.UnmarshalPayload(env.Payload); err != nil {\n    return fmt.Errorf(\"payload is not a valid protobuf: %w\", err)\n}","typeGuard":"func hasValidPayload(env *cb.Envelope) bool {\n    if env == nil || len(env.Payload) == 0 { return false }\n    _, err := protoutil.UnmarshalPayload(env.Payload)\n    return err == nil\n}","tryCatchPattern":"_, err := channelparticipation.ValidateUpdateConfigEnvelope(env)\nif err != nil {\n    if strings.Contains(err.Error(), \"bad payload\") {\n        // regenerate envelope with a properly marshaled payload\n    }\n    return err\n}","preventionTips":["Always build envelopes with protoutil.CreateSignedEnvelope instead of assembling raw structs","Base64-decode and locally unmarshal payloads before submitting to the API","Pin client and orderer Fabric versions to keep protobuf definitions aligned","Log the payload length and first bytes when debugging envelope construction"],"tags":["fabric","orderer","protobuf","malformed-envelope"],"backgroundTag":"malformed-protobuf-payload","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}