{"record":{"id":"0ed5c8207c4a826d","repo":"hyperledger/fabric","slug":"failed-marshaling-fabricmspconfig","errorCode":null,"errorMessage":"failed marshaling FabricMSPConfig","messagePattern":"failed marshaling FabricMSPConfig","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"discovery/support/config/support.go","lineNumber":160,"sourceCode":"func perOrgEndpointsByMSPID(ordererGrp map[string]*common.ConfigGroup) (map[string][]string, error) {\n\tres := make(map[string][]string)\n\n\tfor name, group := range ordererGrp {\n\t\tmspConfig := &msp.MSPConfig{}\n\t\tif err := proto.Unmarshal(group.Values[channelconfig.MSPKey].Value, mspConfig); err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"failed parsing MSPConfig\")\n\t\t}\n\t\t// Skip non fabric MSPs, as they don't carry useful information for service discovery.\n\t\t// An idemix MSP shouldn't appear inside an orderer group, but this isn't a fatal error\n\t\t// for the discovery service and we can just ignore it.\n\t\tif mspConfig.Type != int32(mspconstants.FABRIC) {\n\t\t\tlogger.Error(\"Orderer group\", name, \"is not a FABRIC MSP, but is of type\", mspConfig.Type)\n\t\t\tcontinue\n\t\t}\n\n\t\tfabricConfig := &msp.FabricMSPConfig{}\n\t\tif err := proto.Unmarshal(mspConfig.Config, fabricConfig); err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"failed marshaling FabricMSPConfig\")\n\t\t}\n\n\t\t// Initialize an empty MSP to address mapping.\n\t\tres[fabricConfig.Name] = nil\n\n\t\t// If the key has a corresponding value, it should unmarshal successfully.\n\t\tif perOrgAddresses := group.Values[channelconfig.EndpointsKey]; perOrgAddresses != nil {\n\t\t\tordererEndpoints := &common.OrdererAddresses{}\n\t\t\tif err := proto.Unmarshal(perOrgAddresses.Value, ordererEndpoints); err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"failed unmarshalling orderer addresses\")\n\t\t\t}\n\t\t\t// Override the mapping because this orderer org config contains org-specific endpoints.\n\t\t\tres[fabricConfig.Name] = ordererEndpoints.Addresses\n\t\t}\n\t}\n\n\treturn res, nil\n}","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/discovery/support/config/support.go#L142-L178","documentation":"Despite the wording 'failed marshaling', this error is raised when proto.Unmarshal fails to decode the inner msp.FabricMSPConfig carried inside a FABRIC-type MSPConfig of an orderer org group. The discovery support needs the FabricMSPConfig (notably its Name) to key the endpoints map, so a corrupt inner payload is fatal here. The underlying decode error is wrapped with 'failed marshaling FabricMSPConfig'.","triggerScenarios":"In perOrgEndpointsByMSPID, after mspConfig.Type == FABRIC passes, proto.Unmarshal(mspConfig.Config, &msp.FabricMSPConfig{}) fails because mspConfig.Config is empty, truncated, or was produced from a different message type (e.g. an idemix or other MSP's bytes mislabeled as FABRIC type).","commonSituations":"MSP config generated by mismatched Fabric versions where the embedded config bytes differ; someone set Type=FABRIC but put non-FabricMSPConfig bytes in Config; corrupted config block; test fixtures that fill Type but not Config.","solutions":["Regenerate the organization's MSP definition with configtxgen so mspConfig.Config contains a valid FabricMSPConfig.","Verify MSPConfig.Type actually matches the payload type (FABRIC type must carry FabricMSPConfig bytes).","Round-trip the config through configtxlator to confirm the inner FabricMSPConfig decodes.","Align Fabric versions across components producing and consuming the channel config."],"exampleFix":"// before: type set but payload is raw YAML/other bytes\nmspCfg := &msp.MSPConfig{Type: int32(mspconstants.FABRIC), Config: yamlBytes}\n// after\nfabricCfg, _ := proto.Marshal(&msp.FabricMSPConfig{Name: \"OrdererMSP\", RootCerts: ...})\nmspCfg := &msp.MSPConfig{Type: int32(mspconstants.FABRIC), Config: fabricCfg}","handlingStrategy":"validation","validationCode":"if mspConfig.Type == int32(mspconstants.FABRIC) && len(mspConfig.Config) == 0 {\n    return fmt.Errorf(\"FABRIC MSPConfig has empty embedded config\")\n}\nfabricCfg := &msp.FabricMSPConfig{}\nif err := proto.Unmarshal(mspConfig.Config, fabricCfg); err != nil {\n    return fmt.Errorf(\"embedded FabricMSPConfig invalid: %w\", err)\n}","typeGuard":"func isDecodableFabricMSPConfig(c *msp.MSPConfig) bool {\n    if c.Type != int32(mspconstants.FABRIC) || len(c.Config) == 0 {\n        return false\n    }\n    return proto.Unmarshal(c.Config, &msp.FabricMSPConfig{}) == nil\n}","tryCatchPattern":"if err := proto.Unmarshal(mspConfig.Config, fabricConfig); err != nil {\n    return fmt.Errorf(\"failed marshaling FabricMSPConfig: %w\", err)\n}","preventionTips":["Ensure MSPConfig.Type matches the embedded payload type (FABRIC type must carry FabricMSPConfig bytes).","Validate MSP definitions with configtxgen output before committing them to channel config.","Test org MSP definitions by decoding with configtxlator before channel creation.","Keep Fabric versions aligned between config producers and the discovery service."],"tags":["protobuf","hyperledger-fabric","msp","config"],"backgroundTag":"protobuf-unmarshal-failed","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"}