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

  1. 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).
  2. 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.
  3. Fix any typo in the org's 'ID:' field in configtx.yaml and regenerate the update transaction.
  4. 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

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


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/2de631eba7d9501f. Report an issue: GitHub.