hyperledger/fabric · error
orderer org %s attempted to change MSP ID from %s to %s
Error message
orderer org %s attempted to change MSP ID from %s to %s
What it means
ValidateNew in Hyperledger Fabric's channelconfig enforces that the MSP ID of an existing orderer organization can never be changed via a channel config update. When iterating old vs new orderer orgs, if org.MSPID() differs from norg.MSPID() for the same org name, the update is rejected. MSP IDs are identity anchors for the network; silently swapping them would allow impersonation or break signature verification.
Source
Thrown at common/channelconfig/bundle.go:114
// When we move to capability V3_0 we insist on per Org endpoints for every org
isOldV3 := b.ChannelConfig().Capabilities().ConsensusTypeBFT()
isNewV3 := nb.ChannelConfig().Capabilities().ConsensusTypeBFT()
if !isOldV3 && isNewV3 {
for _, org := range noc.Organizations() {
if len(org.Endpoints()) == 0 {
return errors.Errorf("illegal orderer config update detected: endpoints of org %s are missing", org.Name())
}
}
}
for orgName, org := range oc.Organizations() {
norg, ok := noc.Organizations()[orgName]
if !ok {
continue
}
mspID := org.MSPID()
if mspID != norg.MSPID() {
return errors.Errorf("orderer org %s attempted to change MSP ID from %s to %s", orgName, mspID, norg.MSPID())
}
}
}
if ac, ok := b.ApplicationConfig(); ok {
nac, ok := nb.ApplicationConfig()
if !ok {
return errors.New("current config has application section, but new config does not")
}
for orgName, org := range ac.Organizations() {
norg, ok := nac.Organizations()[orgName]
if !ok {
continue
}
mspID := org.MSPID()
if mspID != norg.MSPID() {
return errors.Errorf("application org %s attempted to change MSP ID from %s to %s", orgName, mspID, norg.MSPID())View on GitHub (pinned to 2736b63f8f)
Solutions
- Keep the MSP ID in the new config identical to the current one for that org name (check with configtxlator decode of both current and updated configs).
- If the org truly needs a new MSP ID, create a NEW organization with a different name and add it, then remove the old one through the proper update sequence.
- Fix any typo in the org's 'ID:' field in configtx.yaml and regenerate the update transaction.
- Compare 'fabric channel fetch config' output before/after your edit to spot the MSP ID delta before submitting.
Example fix
// before (configtx.yaml) - &OrdererOrg Name: OrdererOrg ID: NewOrdererMSP # changed from OrdererMSP // after - &OrdererOrg Name: OrdererOrg ID: OrdererMSP # MSP ID must stay immutable for existing orgs
Defensive patterns
Strategy: validation
Validate before calling
// Verify orderer org MSP IDs are unchanged before proposing an update
func checkMSPIDsUnchanged(current, proposed map[string]*cb.ConfigGroup) error {
for name, old := range current {
newG, ok := proposed[name]
if !ok {
continue
}
oldID := mspIDOf(old)
if newID := mspIDOf(newG); oldID != "" && oldID != newID {
return fmt.Errorf("org %s MSP ID change detected: %s -> %s", name, oldID, newID)
}
}
return nil
} Type guard
func orgHasMSPID(g *cb.ConfigGroup, want string) bool {
v, ok := g.Values["MSP"]
if !ok || v == nil {
return false
}
var msp mspconfig.MSPConfig
if err := proto.Unmarshal(v.Value, &msp); err != nil {
return false
}
return string(msp.Name) == want
} Try / catch
if err := configtxManager.ProposeConfigUpdate(env); err != nil {
if strings.Contains(err.Error(), "attempted to change MSP ID") {
// do not retry; restore the original MSP ID and regenerate the update
return fmt.Errorf("immutable MSP ID violation: %w", err)
}
return err
} Prevention
- Treat MSP IDs as immutable: never edit the ID: field of an existing org in configtx.yaml
- Always fetch and diff the live channel config against your proposed config before submitting
- Give new organizations unique names instead of reusing names with new MSPs
- Keep crypto material and configtx IDs in sync when regenerating certificates
When it happens
Trigger: Submitting a channel config update where an organization under the Orderer group keeps its name but its MSP ID (the value in its MSP config value, org.MSPID(), derived from the config 'MSP' value / configtx 'ID' field) differs from the current config.
Common situations: Copy-paste typos in configtx.yaml where an org's ID was edited; reusing an org name for a different organization with a new MSP; merging configs from different networks where the same org name maps to different MSP IDs; accidentally regenerating crypto material under a different MSP name.
Related errors
- application org %s attempted to change MSP ID from %s to %s
- illegal orderer config update detected: endpoints of org %s
- current config has application section, but new config does
- current config has consortiums section, but new config does
- Attempted to define two different versions of MSP: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/2de631eba7d9501f.
Report an issue: GitHub.