{"record":{"id":"a32de73068127b72","repo":"hyperledger/fabric","slug":"envelope-must-have-a-header","errorCode":null,"errorMessage":"envelope must have a Header","messagePattern":"envelope must have a Header","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"protoutil/commonutils.go","lineNumber":66,"sourceCode":"\treturn nonce\n}\n\n// CreateNonce generates a nonce using the common/crypto package.\nfunc CreateNonce() ([]byte, error) {\n\tnonce, err := getRandomNonce()\n\treturn nonce, errors.WithMessage(err, \"error generating random nonce\")\n}\n\n// UnmarshalEnvelopeOfType unmarshals an envelope of the specified type,\n// including unmarshalling the payload data\nfunc UnmarshalEnvelopeOfType(envelope *cb.Envelope, headerType cb.HeaderType, message proto.Message) (*cb.ChannelHeader, error) {\n\tpayload, err := UnmarshalPayload(envelope.Payload)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif payload.Header == nil {\n\t\treturn nil, errors.New(\"envelope must have a Header\")\n\t}\n\n\tchdr, err := UnmarshalChannelHeader(payload.Header.ChannelHeader)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif chdr.Type != int32(headerType) {\n\t\treturn nil, errors.Errorf(\"invalid type %s, expected %s\", cb.HeaderType(chdr.Type), headerType)\n\t}\n\n\terr = proto.Unmarshal(payload.Data, message)\n\terr = errors.Wrapf(err, \"error unmarshalling message for type %s\", headerType)\n\treturn chdr, err\n}\n\n// ExtractEnvelopeOrPanic retrieves the requested envelope from a given block\n// and unmarshals it -- it panics if either of these operations fail","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/protoutil/commonutils.go#L48-L84","documentation":"UnmarshalEnvelopeOfType unmarshals the envelope's Payload and then requires payload.Header to be present, since the channel header and signature header needed for type/channel validation live there. A payload without a Header cannot be routed or authenticated, so the function returns 'envelope must have a Header'.","triggerScenarios":"Calling UnmarshalEnvelopeOfType (directly or via ProcessConfigMsg, Apply, validateConfigBlock, extractChannelConfig) with an envelope whose inner payload.Header is nil — e.g. a payload built without SetHeader or a payload deserialized from tampered data.","commonSituations":"Submitting config/transaction messages constructed manually without a header; corrupted payloads read from storage; test envelopes missing &cb.Payload{Header: ...}; middleware that rebuilt the payload and dropped the header.","solutions":["Populate the payload header before marshaling: use protoutil.MakeChannelHeader and BuildHeader, and set payload.Header.ChannelHeader/SignatureHeader.","Verify the client/proxy that creates the message actually attaches a header.","Validate incoming envelopes early and reject those without headers with a clearer application-level error.","If reading from a block, re-fetch from a trusted source — the payload may be corrupt."],"exampleFix":"// before\npayload := &cb.Payload{Data: data}\n// after\nchdr := protoutil.MakeChannelHeader(cb.HeaderType_ENDORSER_TRANSACTION, 0, channelID, 0)\npayload := &cb.Payload{Header: protoutil.MakePayloadHeader(chdr, sighdr), Data: data}","handlingStrategy":"validation","validationCode":"env := &cb.Envelope{}\n_ = proto.Unmarshal(raw, env)\npayload := &cb.Payload{}\n_ = proto.Unmarshal(env.Payload, payload)\nif payload.Header == nil || len(payload.Header.ChannelHeader) == 0 {\n\treturn errors.New(\"payload must carry a Header with ChannelHeader\")\n}","typeGuard":"func hasHeader(payload *cb.Payload) bool {\n\treturn payload != nil && payload.Header != nil && len(payload.Header.ChannelHeader) > 0\n}","tryCatchPattern":null,"preventionTips":["Always build payloads with protoutil.MakePayloadHeader / BuildHeader.","Validate envelopes (header present, type correct) at the ingress boundary.","Never rebuild Payload structs manually in middleware.","Include header-presence assertions in integration tests for message submission."],"tags":["hyperledger-fabric","protobuf","envelope","validation"],"backgroundTag":"missing-payload-header","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"}