{"record":{"id":"7e2d3d54e42907a8","repo":"hyperledger/fabric","slug":"invalid-type-s-expected-s","errorCode":null,"errorMessage":"invalid type %s, expected %s","messagePattern":"invalid type (.+?), expected (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"protoutil/commonutils.go","lineNumber":75,"sourceCode":"// 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\nfunc ExtractEnvelopeOrPanic(block *cb.Block, index int) *cb.Envelope {\n\tenvelope, err := ExtractEnvelope(block, index)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn envelope\n}\n\n// ExtractEnvelope retrieves the requested envelope from a given block and","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/protoutil/commonutils.go#L57-L93","documentation":"UnmarshalEnvelopeOfType unmarshals an envelope payload into a message and verifies the envelope's channel header type matches the expected header type. This error is thrown when the envelope's decoded header type (e.g. HEADER_TYPE_ENDORSER_TRANSACTION) does not match the headerType argument the caller requested. It is a type-mismatch guard, not a corruption error: the envelope parsed fine, it just isn't the kind of message the caller expected.","triggerScenarios":"Calling UnmarshalEnvelopeOfType with a specific cb.HeaderType (e.g. cb.HeaderType_CONFIG) against an envelope whose ChannelHeader.Type differs — e.g. passing an orderer config block to a function expecting a transaction, or feeding an ENDORSER_TRANSACTION envelope into a CONFIG decoder.","commonSituations":"Delivering blocks/transactions to the wrong processing path; peer/orderer code validating that a block actually contains a config transaction before applying it (ProcessConfigMsg, validateConfigBlock); fabric-sdk or external tooling submitting a payload of the wrong type for a channel; config updates sent as normal transactions.","solutions":["Check the actual header type of your envelope: unmarshal the payload and inspect chdr.Type, then route it to the matching decoder instead of the expected one.","Verify you are passing the correct cb.HeaderType constant to UnmarshalEnvelopeOfType for the data you actually have.","If the envelope should be of the expected type, trace its producer (transaction proposal or config update) — the submitting component built the wrong payload type.","For genesis/config blocks, ensure the block you feed to channelConfigFromBlock/extractChannelConfig is a config block (IsConfigBlock) not an ordinary block with transactions."],"exampleFix":"// before\nenvelope, _ := ExtractEnvelope(block, 0)\nvar config cb.ConfigEnvelope\nerr := protoutil.UnmarshalEnvelopeOfType(envelope, cb.HeaderType_CONFIG, &config) // fails: envelope is a transaction\n// after\nchdr, _ := protoutil.ChannelHeader(envelope)\nif cb.HeaderType(chdr.Type) == cb.HeaderType_CONFIG {\n    err = protoutil.UnmarshalEnvelopeOfType(envelope, cb.HeaderType_CONFIG, &config)\n} else {\n    err = protoutil.UnmarshalEnvelopeOfType(envelope, cb.HeaderType_ENDORSER_TRANSACTION, &tx)\n}","handlingStrategy":"validation","validationCode":"func hasHeaderType(t *testing.T, env *cb.Envelope, want cb.HeaderType) bool {\n    chdr, err := protoutil.ChannelHeader(env)\n    if err != nil {\n        return false\n    }\n    return cb.HeaderType(chdr.Type) == want\n}\n// call protoutil.UnmarshalEnvelopeOfType(env, want, msg) only when hasHeaderType(env, want)","typeGuard":"func envelopeHasType(env *cb.Envelope, want cb.HeaderType) bool {\n    chdr, err := protoutil.ChannelHeader(env)\n    return err == nil && cb.HeaderType(chdr.Type) == want\n}","tryCatchPattern":"var msg cb.ConfigEnvelope\nif err := protoutil.UnmarshalEnvelopeOfType(env, cb.HeaderType_CONFIG, &msg); err != nil {\n    // inspect actual type and route accordingly\n    chdr, herr := protoutil.ChannelHeader(env)\n    if herr == nil {\n        return fmt.Errorf(\"expected CONFIG, got %s: %w\", cb.HeaderType(chdr.Type), err)\n    }\n    return err\n}","preventionTips":["Inspect chdr.Type and branch on it before choosing a decoder type","Use IsConfigBlock/HasConfigTx to confirm a block is a config block before config decoding","Keep fabric-protos versions consistent across producing and consuming components","Unit-test envelope construction paths so header type always matches payload message"],"tags":["hyperledger-fabric","protobuf","type-mismatch"],"backgroundTag":"protobuf-type-mismatch","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"}