{"record":{"id":"85902f5849b317bc","repo":"hyperledger/fabric","slug":"channel-header-not-set","errorCode":null,"errorMessage":"channel header not set","messagePattern":"channel header not set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"protoutil/commonutils.go","lineNumber":250,"sourceCode":"}\n\n// ChannelHeader returns the *cb.ChannelHeader for a given *cb.Envelope.\nfunc ChannelHeader(env *cb.Envelope) (*cb.ChannelHeader, error) {\n\tif env == nil {\n\t\treturn nil, errors.New(\"Invalid envelope payload. can't be nil\")\n\t}\n\n\tenvPayload, err := UnmarshalPayload(env.Payload)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif envPayload.Header == nil {\n\t\treturn nil, errors.New(\"header not set\")\n\t}\n\n\tif envPayload.Header.ChannelHeader == nil {\n\t\treturn nil, errors.New(\"channel header not set\")\n\t}\n\n\tchdr, err := UnmarshalChannelHeader(envPayload.Header.ChannelHeader)\n\tif err != nil {\n\t\treturn nil, errors.WithMessage(err, \"error unmarshalling channel header\")\n\t}\n\n\treturn chdr, nil\n}\n\n// ChannelID returns the Channel ID for a given *cb.Envelope.\nfunc ChannelID(env *cb.Envelope) (string, error) {\n\tchdr, err := ChannelHeader(env)\n\tif err != nil {\n\t\treturn \"\", errors.WithMessage(err, \"error retrieving channel header\")\n\t}\n\n\treturn chdr.ChannelId, nil","sourceCodeStart":232,"sourceCodeEnd":268,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/protoutil/commonutils.go#L232-L268","documentation":"ChannelHeader() found a Header on the payload but the Header.ChannelHeader field is nil, so there is no serialized channel header to unmarshal. Every transaction/config envelope must embed a ChannelHeader containing channel ID, txid, epoch and creator; without it the envelope cannot be routed.","triggerScenarios":"Calling ChannelHeader/ChannelID/BroadcastChannelSupport/ConfigChannelHeader/ConfigEnvelopeFromBlock on an envelope whose Payload.Header exists but has an empty ChannelHeader byte slice — typically an envelope constructed with only a SignatureHeader set, or a header copied from a different message type.","commonSituations":"Manual envelope assembly in SDKs or tests where Header was partially populated; copying a Header struct field-by-field and forgetting ChannelHeader; corrupt payload from a bad producer.","solutions":["Populate Header.ChannelHeader with marshaled &common.ChannelHeader bytes (use protoutil.MakeChannelHeader and Marshal) before wrapping in a payload","Use protoutil.BuildChannelHeader + protoutil.MakePayload instead of assembling Header by hand","Validate before use: check len(payload.Header.ChannelHeader) > 0 before calling ChannelHeader","Fix the upstream producer that emits envelopes without channel headers"],"exampleFix":"// before\nhdr := &common.Header{SignatureHeader: sigHdr} // ChannelHeader missing\n// after\nchdr := protoutil.MakeChannelHeader(common.HeaderType_ENDORSER_TRANSACTION, 0, \"mychannel\", chaincodeID)\nhdr := &common.Header{ChannelHeader: protoutil.MarshalOrPanic(chdr), SignatureHeader: sigHdr}","handlingStrategy":"validation","validationCode":"payload, err := protoutil.UnmarshalPayload(env.Payload)\nif err != nil { return err }\nif payload.Header == nil { return errors.New(\"header not set\") }\nif len(payload.Header.ChannelHeader) == 0 { return errors.New(\"channel header bytes missing\") }","typeGuard":"func hasChannelHeader(env *common.Envelope) bool {\n\tp, err := protoutil.UnmarshalPayload(env.GetPayload())\n\treturn err == nil && p != nil && p.Header != nil && len(p.Header.ChannelHeader) > 0\n}","tryCatchPattern":"chdr, err := protoutil.ChannelHeader(env)\nif err != nil {\n\tif strings.Contains(err.Error(), \"not set\") {\n\t\treturn fmt.Errorf(\"envelope lacks channel header; reject or re-request: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Use protoutil.MakeChannelHeader + MarshalOrPanic when assembling headers","Never copy Header structs partially; use protoutil.MakePayload to bind ChannelHeader and SignatureHeader together","Reject malformed envelopes at gossip/ingress with clear producer attribution"],"tags":["fabric","protobuf","missing-header","channel-header"],"backgroundTag":"missing-required-argument","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"}