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
After successfully unmarshalling the chaincode event, VSCC checks that ccEvent.ChaincodeId equals the invoked chaincode's name (ccID from the header extension). A mismatch means the event claims a different chaincode than the action's chaincode, indicating forged or misattributed events, so the transaction is invalid with TxValidationCode_INVALID_OTHER_REASON.
Source
Thrown at core/committer/txvalidator/v14/vscc_validator.go:127
}
// sanity check on ccver
if ccVer == "" {
err = errors.New("invalid chaincode version")
logger.Errorf("%+v", err)
return peer.TxValidationCode_INVALID_OTHER_REASON, err
}
var wrNamespace []string
alwaysEnforceOriginalNamespace := v.cr.Capabilities().V1_2Validation()
if alwaysEnforceOriginalNamespace {
wrNamespace = append(wrNamespace, ccID)
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 {
return peer.TxValidationCode_ILLEGAL_WRITESET, errors.Errorf("duplicate namespace '%s' in txRWSet", ns.NameSpace)
}
namespaces[ns.NameSpace] = struct{}{}
if !v.txWritesToNamespace(ns) {
continue
}
// Check to make sure we did not already populate this chaincode
// name to avoid checking the same namespace twiceView on GitHub (pinned to 2736b63f8f)
Solutions
- Fix the chaincode so events are created only via stub.SetEvent, which sets ChaincodeId to the current chaincode.
- Remove or correct any manually populated ChaincodeId in event structs inside the chaincode.
- Audit shared helper/SDK code that constructs ChaincodeEvent objects for the whole network.
Example fix
// before
evt := &peer.ChaincodeEvent{ChaincodeId: "othercc", EventName: "e"}
// after
stub.SetEvent("e", payload) // shim fills ChaincodeId automatically Defensive patterns
Strategy: validation
Validate before calling
if ccEvent.ChaincodeId != ccID {
return fmt.Errorf("event chaincode id %q does not match action chaincode id %q", ccEvent.ChaincodeId, ccID)
} Type guard
func eventMatchesChaincode(evt *peer.ChaincodeEvent, expectedID string) bool {
return evt != nil && evt.ChaincodeId == expectedID
} Try / catch
if ccEvent.ChaincodeId != ccID {
logger.Warnf("tx rejected: event chaincode id mismatch (%s != %s)", ccEvent.ChaincodeId, ccID)
return peer.TxValidationCode_INVALID_OTHER_REASON, nil
} Prevention
- Create events exclusively via stub.SetEvent so the shim fills ChaincodeId.
- Do not hardcode chaincode IDs inside chaincode event structs.
- Review any shared event-emitting helpers across your chaincodes.
When it happens
Trigger: A chaincode (or payload tamperer) emits an event whose ChaincodeId field differs from the chaincode that produced the action — e.g. copying event structs from another chaincode's stub, or manually constructing events with a wrong ChaincodeId.
Common situations: Chaincode code that hardcodes another chaincode's ID in its event struct; generic event-emitting helper libraries setting an incorrect ID; deliberate tampering blocked by validation.
Related errors
- invalid chaincode event
- error unmarshalling ChaincodeHeaderExtension
- nil ChaincodeId in header extension
- nil ChaincodeId in ChaincodeAction
- invalid chaincode ID
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/8b26a786c5b3cb00.
Report an issue: GitHub.