{"record":{"id":"600e077f5add9532","repo":"hyperledger/fabric","slug":"unexpected-envelope-type-s","errorCode":null,"errorMessage":"unexpected envelope type %s","messagePattern":"unexpected envelope type (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/consensus/smartbft/configverifier.go","lineNumber":90,"sourceCode":"\n\tif payload.Header.ChannelHeader == nil {\n\t\treturn fmt.Errorf(\"no channel header was set\")\n\t}\n\n\tchdr, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"channel header unmarshalling error: %s\", err)\n\t}\n\n\tswitch chdr.Type {\n\tcase int32(common.HeaderType_CONFIG):\n\t\tconfigEnvelope := &common.ConfigEnvelope{}\n\t\tif err = proto.Unmarshal(payload.Data, configEnvelope); err != nil {\n\t\t\treturn fmt.Errorf(\"data unmarshalling error: %s\", err)\n\t\t}\n\t\treturn cbv.verifyConfigUpdateMsg(envelope, configEnvelope, chdr)\n\tdefault:\n\t\treturn errors.Errorf(\"unexpected envelope type %s\", common.HeaderType_name[chdr.Type])\n\t}\n}\n\nfunc (cbv *ConfigBlockValidator) checkConsentersMatchPolicy(conf *common.Config) error {\n\tif conf == nil {\n\t\treturn fmt.Errorf(\"empty Config\")\n\t}\n\n\tif conf.ChannelGroup == nil {\n\t\treturn fmt.Errorf(\"empty channel group\")\n\t}\n\n\tif len(conf.ChannelGroup.Groups) == 0 {\n\t\treturn fmt.Errorf(\"no groups in channel group\")\n\t}\n\n\tif conf.ChannelGroup.Groups[\"Orderer\"] == nil {\n\t\treturn fmt.Errorf(\"no 'Orderer' group in channel groups\")","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/consensus/smartbft/configverifier.go#L72-L108","documentation":"ValidateConfig only accepts envelopes whose channel header type is HeaderType_CONFIG. Any other header type (e.g. TRANSACTION, CONFIG_UPDATE, DELIVER_SEEK_INFO) falls into the default case and is rejected with 'unexpected envelope type <name>'. This guards the SmartBFT config block validation path so only committed config blocks are processed.","triggerScenarios":"Calling ConfigBlockValidator.ValidateConfig with an envelope whose ChannelHeader.Type is not int32(common.HeaderType_CONFIG) — e.g. passing a CONFIG_UPDATE transaction, an endorser transaction, or an envelope with a zero/unset (UNKNOWN) header type.","commonSituations":"Submitting a config update envelope (type CONFIG_UPDATE) instead of the resulting config block's envelope; feeding regular application transactions into the config validation path; constructing envelopes by hand and forgetting to set the channel header type; misconfigured deliver clients injecting non-config envelopes.","solutions":["Pass the committed CONFIG block's envelope (header type CONFIG), not the CONFIG_UPDATE submission envelope","Verify payload.Header.ChannelHeader.Type is set to common.HeaderType_CONFIG before calling ValidateConfig","If handling a config update submission, first run it through the orderer's broadcast/ProposeConfigUpdate flow to produce a CONFIG envelope","Regenerate the envelope via protoutil (CreateSignedEnvelope with common.HeaderType_CONFIG) if it was built manually"],"exampleFix":"// before\nenv.HeaderType = common.HeaderType_CONFIG_UPDATE\nvalidator.ValidateConfig(env) // -> unexpected envelope type CONFIG_UPDATE\n// after\nenv.HeaderType = common.HeaderType_CONFIG\nvalidator.ValidateConfig(env) // OK","handlingStrategy":"validation","validationCode":"func isConfigEnvelope(env *common.Envelope) bool {\n  payload := &common.Payload{}\n  if proto.Unmarshal(env.Payload, payload) != nil || payload.Header == nil {\n    return false\n  }\n  chdr := &common.ChannelHeader{}\n  if proto.Unmarshal(payload.Header.ChannelHeader, chdr) != nil {\n    return false\n  }\n  return chdr.Type == int32(common.HeaderType_CONFIG)\n}","typeGuard":"func guardConfigType(chdr *common.ChannelHeader) bool {\n  return chdr != nil && common.HeaderType(chdr.Type) == common.HeaderType_CONFIG\n}","tryCatchPattern":"if err := cbv.ValidateConfig(envelope); err != nil {\n  if strings.Contains(err.Error(), \"unexpected envelope type\") {\n    // wrong header type; route to the appropriate validator for this HeaderType\n    return handleNonConfigEnvelope(envelope, err)\n  }\n  return err\n}","preventionTips":["Only feed committed config blocks (type CONFIG) into ValidateConfig","Check ChannelHeader.Type before dispatching envelopes to validators","Use protoutil helpers (ChannelID/UnmarshalChannelHeader) to assert type and channel before validation","In tests, build envelopes with protoutil.CreateSignedEnvelope(common.HeaderType_CONFIG, ...)"],"tags":["hyperledger-fabric","smartbft","envelope-type","config-validation"],"backgroundTag":"unexpected-envelope-type","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"}