hyperledger/fabric · error

application org attempted to change MSP ID from to

Error message

application org %s attempted to change MSP ID from %s to %s

What it means

Analogous to the orderer case, ValidateNew forbids changing the MSP ID of an existing application organization. If an application org keeps its name across a config update but its MSPID() changes, the update is rejected. This preserves the integrity of org identities that anchor ACL and endorsement policies on the channel.

Solutions

  1. Keep the application org's MSP ID unchanged in the new config; diff current vs proposed config with configtxlator to confirm.
  2. If a re-keying is genuinely needed, add a new org with a new name/MSP ID, update policies/ACLs, then remove the old org in a subsequent update.
  3. Correct the typo in the org's 'ID:' field and rebuild the update transaction.
  4. Fetch the live channel config ('peer channel fetch config') and programmatically compare MSP values before submitting the update.

Example fix

// before (configtx.yaml)
- &Org1
  Name: Org1
  ID: Org1NewMSP    # changed from Org1MSP
// after
- &Org1
  Name: Org1
  ID: Org1MSP       # unchanged
Defensive patterns

Strategy: validation

Validate before calling

// Validate application org MSP IDs are preserved before proposing the update
func checkAppMSPIDs(current, proposed *cb.Config) error {
	curApp := current.Groups["Application"]
	newApp, ok := proposed.Groups["Application"]
	if curApp == nil || !ok {
		return nil
	}
	for name, old := range curApp.Groups {
		if newG, ok := newApp.Groups[name]; ok && mspIDOf(old) != mspIDOf(newG) {
			return fmt.Errorf("app org %s MSP ID would change", name)
		}
	}
	return nil
}

Type guard

func sameMSPID(a, b *cb.ConfigGroup) bool {
	return mspIDOf(a) != "" && mspIDOf(a) == mspIDOf(b)
}

Try / catch

if err := configtxManager.ProposeConfigUpdate(env); err != nil {
	if strings.Contains(err.Error(), "application org") && strings.Contains(err.Error(), "MSP ID") {
		return fmt.Errorf("revert the MSP ID change and resubmit: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: A channel config update transaction where an organization in channel->groups->Application->groups has the same name but a different MSP value (ID) than the currently committed config.

Common situations: Hand-editing an org's ID in configtx.yaml; importing a peer org from a different network with the same Name but a different MSP ID; crypto material regenerated under a different CA subject/MSP name and reflected in the config; automation scripts templating MSP IDs incorrectly.

Related errors


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

Appendix: source

Thrown at common/channelconfig/bundle.go:132

				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())
			}
		}
	}

	if cc, ok := b.ConsortiumsConfig(); ok {
		ncc, ok := nb.ConsortiumsConfig()
		if !ok {
			return errors.Errorf("current config has consortiums section, but new config does not")
		}

		for consortiumName, consortium := range cc.Consortiums() {
			nconsortium, ok := ncc.Consortiums()[consortiumName]
			if !ok {
				continue
			}

			for orgName, org := range consortium.Organizations() {
				norg, ok := nconsortium.Organizations()[orgName]

View on GitHub (pinned to 2736b63f8f)