hyperledger/fabric · error

chaincode event chaincode id does not match chaincode action

Error message

chaincode event chaincode id does not match chaincode action chaincode id

What it means

During Dispatch validation, the unmarshaled ChaincodeEvent's ChaincodeId does not equal the chaincode ID from the header extension (ccID). Fabric throws this because an event claiming to come from a different chaincode than the executing transaction is inconsistent (spoofing or bug) and invalidates the tx.

Source

Thrown at core/committer/txvalidator/v20/plugindispatcher/dispatcher.go:167

		logger.Errorf("%+v", err)
		return peer.TxValidationCode_INVALID_CHAINCODE, err
	}
	// sanity check on ccver
	if ccVer == "" {
		err = errors.New("invalid chaincode version")
		logger.Errorf("%+v", err)
		return peer.TxValidationCode_INVALID_CHAINCODE, err
	}

	wrNamespace := map[string]bool{}
	wrNamespace[ccID] = true
	if respPayload.Events != nil {
		ccEvent := &peer.ChaincodeEvent{}
		if err = proto.Unmarshal(respPayload.Events, ccEvent); err != nil {
			return peer.TxValidationCode_INVALID_OTHER_REASON, errors.Wrapf(err, "invalid chaincode event")
		}
		if ccEvent.ChaincodeId != ccID {
			return peer.TxValidationCode_INVALID_OTHER_REASON, errors.Errorf("chaincode event chaincode id does not match chaincode action chaincode id")
		}
	}

	namespaces := make(map[string]struct{})
	for _, ns := range txRWSet.NsRwSets {
		// check to make sure there is no duplicate namespace in txRWSet
		if _, ok := namespaces[ns.NameSpace]; ok {
			logger.Errorf("duplicate namespace '%s' in txRWSet", ns.NameSpace)
			return peer.TxValidationCode_ILLEGAL_WRITESET,
				errors.Errorf("duplicate namespace '%s' in txRWSet", ns.NameSpace)
		}
		namespaces[ns.NameSpace] = struct{}{}

		if v.txWritesToNamespace(ns) {
			wrNamespace[ns.NameSpace] = true
		}
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Fix the chaincode so events are emitted through shim.SetEvent, letting the shim/endorser stamp the correct ChaincodeId instead of hard-coding it.
  2. Audit shared chaincode code for stale hard-coded chaincode names in events.
  3. Regenerate the failing transaction after the chaincode fix.
  4. If malicious, reject the tx (the validator already does) and investigate the submitter.

Example fix

// before
ccEvent := &peer.ChaincodeEvent{ChaincodeId: "othercc", EventName: "e"}
// after
stub.SetEvent("e", payload) // ChaincodeId derived from executing chaincode
Defensive patterns

Strategy: validation

Validate before calling

// before endorsing, verify event attribution
if (ccEvent.chaincodeId && ccEvent.chaincodeId !== invokingChaincodeId) { throw new Error('event chaincode id does not match action'); }

Type guard

function eventBelongsToChaincode(ev, ccId) { return !ev?.chaincodeId || ev.chaincodeId === ccId; }

Try / catch

try { validate(tx); } catch (err) { if (/event chaincode id does not match/.test(err.message)) { /* reject tx; investigate emitting chaincode */ } else { throw err; } }

Prevention

When it happens

Trigger: Chaincode emits an event whose ChaincodeId field (set by the shim/endorser) differs from the chaincode named in the proposal header — e.g. one chaincode fabricates an event attributed to another, or headers/payloads are mixed.

Common situations: Cross-chaincode event spoofing attempts; copy-pasted event-emitting code in shared chaincode repos where the ID constant was not updated; event created through custom serialization that hard-coded another cc ID.

Related errors


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