{"record":{"id":"cad5a9030c8d3d23","repo":"hyperledger/fabric","slug":"attempted-to-define-two-different-versions-of-msp","errorCode":null,"errorMessage":"Attempted to define two different versions of MSP: %s","messagePattern":"Attempted to define two different versions of MSP: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/channelconfig/msp.go","lineNumber":85,"sourceCode":"\t\tif err != nil {\n\t\t\treturn nil, errors.WithMessage(err, \"creating the MSP manager failed\")\n\t\t}\n\tdefault:\n\t\treturn nil, errors.New(fmt.Sprintf(\"Setup error: unsupported msp type %d\", mspConfig.Type))\n\t}\n\n\t// set it up\n\terr = theMsp.Setup(mspConfig)\n\tif err != nil {\n\t\treturn nil, errors.WithMessage(err, \"setting up the MSP manager failed\")\n\t}\n\n\t// add the MSP to the map of pending MSPs\n\tmspID, _ := theMsp.GetIdentifier()\n\n\texistingPendingMSPConfig, ok := bh.idMap[mspID]\n\tif ok && !proto.Equal(existingPendingMSPConfig.mspConfig, mspConfig) {\n\t\treturn nil, errors.New(fmt.Sprintf(\"Attempted to define two different versions of MSP: %s\", mspID))\n\t}\n\n\tif !ok {\n\t\tbh.idMap[mspID] = &pendingMSPConfig{\n\t\t\tmspConfig: mspConfig,\n\t\t\tmsp:       theMsp,\n\t\t}\n\t}\n\n\treturn theMsp, nil\n}\n\nfunc (bh *MSPConfigHandler) CreateMSPManager() (msp.MSPManager, error) {\n\tmspList := make([]msp.MSP, len(bh.idMap))\n\ti := 0\n\tfor _, pendingMSP := range bh.idMap {\n\t\tmspList[i] = pendingMSP.msp\n\t\ti++","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/channelconfig/msp.go#L67-L103","documentation":"ProposeMSP tracks pending MSPs by identifier in bh.idMap. If an MSP with the same ID already exists in the pending set but its proto config differs from the new one, it rejects with 'Attempted to define two different versions of MSP: %s'. This prevents a config update from redefining an existing MSP with different material under the same identity.","triggerScenarios":"A single channel config (or config update) contains two MSP definitions with the same MSP ID but different Config bytes — e.g. different root certs, admin certs, or crypto material for the same org MSP name.","commonSituations":"Redefining an org's MSP (rotating certs) without removing/re-adding the org; duplicate org definitions in configtx.yaml with the same MSP ID but divergent material; copying an org and editing its certs while keeping the same name.","solutions":["Ensure each MSP ID appears exactly once in the config; remove duplicate org/MSP entries","For cert rotation, replace the existing MSP config atomically rather than adding a second definition with the same ID","Use configtxlator to diff the current and updated config and find the MSP defined twice","If the MSPs truly are identical, ensure the bytes match exactly — different serialization of equal material still triggers this"],"exampleFix":"// before: two orgs with same MSP ID but different certs\norganizations:\n  Org1:\n    MSPId: Org1MSP\n    ...certs-v1...\n  Org1New:\n    MSPId: Org1MSP\n    ...certs-v2...\n// after: one definition, one MSP ID\norganizations:\n  Org1:\n    MSPId: Org1MSP\n    ...updated-certs...","handlingStrategy":"validation","validationCode":"seen := map[string]bool{}\nfor orgName, org := range config.Organizations {\n    if seen[org.MSPID] {\n        return fmt.Errorf(\"MSP ID %s (org %s) defined more than once\", org.MSPID, orgName)\n    }\n    seen[org.MSPID] = true\n}","typeGuard":"func uniqueMSPIDs(groups map[string]*cb.ConfigGroup) bool {\n    ids := map[string]bool{}\n    for _, g := range groups {\n        id := mspIDFromGroup(g) // extract MSP ID from the group's MSP value\n        if ids[id] {\n            return false\n        }\n        ids[id] = true\n    }\n    return true\n}","tryCatchPattern":"_, err := ProposeMSP(bh, mspConfig)\nif err != nil && strings.Contains(err.Error(), \"two different versions of MSP\") {\n    return fmt.Errorf(\"MSP ID redefined with different material; use configtxlator to diff configs: %w\", err)\n}","preventionTips":["Keep each MSP ID unique across the whole channel config","Replace MSP material via a single atomic update of the existing org, not an added duplicate","Diff consecutive configs with configtxlator before committing updates","When copying org blocks in configtx.yaml, rename both the org and MSPID"],"tags":["hyperledger-fabric","msp","duplicate-definition","config-update"],"backgroundTag":"duplicate-msp-definition","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"}