hyperledger/fabric · error
expected cc name %s, found %s
Error message
expected cc name %s, found %s
What it means
After successfully unmarshalling ChaincodeData from the lscc write-set, the validator checks that its Name matches the chaincode name in the submitted ChaincodeDeploymentSpec. A mismatch means the lscc rwset records a different chaincode than the one the transaction claims to deploy/upgrade, so the transaction is rejected as a policy violation.
Source
Thrown at core/handlers/validation/builtin/v13/lscc_validation_logic.go:475
return policyErr(fmt.Errorf("No read write set for lscc was found"))
}
// there must be at least one write
if len(lsccrwset.Writes) < 1 {
return policyErr(fmt.Errorf("LSCC must issue at least one single putState upon deploy/upgrade"))
}
// the first key name must be the chaincode id provided in the deployment spec
if lsccrwset.Writes[0].Key != cdsArgs.ChaincodeSpec.ChaincodeId.Name {
return policyErr(fmt.Errorf("expected key %s, found %s", cdsArgs.ChaincodeSpec.ChaincodeId.Name, lsccrwset.Writes[0].Key))
}
// the value must be a ChaincodeData struct
cdRWSet := &ccprovider.ChaincodeData{}
err = proto.Unmarshal(lsccrwset.Writes[0].Value, cdRWSet)
if err != nil {
return policyErr(fmt.Errorf("unmarshalling of ChaincodeData failed, error %s", err))
}
// the chaincode name in the lsccwriteset must match the chaincode name in the deployment spec
if cdRWSet.Name != cdsArgs.ChaincodeSpec.ChaincodeId.Name {
return policyErr(fmt.Errorf("expected cc name %s, found %s", cdsArgs.ChaincodeSpec.ChaincodeId.Name, cdRWSet.Name))
}
// the chaincode version in the lsccwriteset must match the chaincode version in the deployment spec
if cdRWSet.Version != cdsArgs.ChaincodeSpec.ChaincodeId.Version {
return policyErr(fmt.Errorf("expected cc version %s, found %s", cdsArgs.ChaincodeSpec.ChaincodeId.Version, cdRWSet.Version))
}
// it must only write to 2 namespaces: LSCC's and the cc that we are deploying/upgrading
for _, ns := range txRWSet.NsRwSets {
if ns.NameSpace != "lscc" && ns.NameSpace != cdRWSet.Name && len(ns.KvRwSet.Writes) > 0 {
return policyErr(fmt.Errorf("LSCC invocation is attempting to write to namespace %s", ns.NameSpace))
}
}
logger.Debugf("Validating %s for cc %s version %s", lsccFunc, cdRWSet.Name, cdRWSet.Version)
switch lsccFunc {
case lscc.DEPLOY:
/******************************************************************/View on GitHub (pinned to 2736b63f8f)
Solutions
- Rebuild the deploy/upgrade proposal with the SDK/lifecycle tooling so ChaincodeData.Name is generated from ChaincodeSpec.ChaincodeId.Name.
- If using custom tooling, ensure the ChaincodeData written by lscc uses exactly the ChaincodeId.Name from the proposal.
- Do not reuse cached/pre-serialized ChaincodeData across different chaincode deployments.
- Confirm you are not replaying a proposal captured for another chaincode or channel.
Example fix
// before: stale data blob from another cc
cd.Name = "oldcc"
// after: derive from the deployment spec
cd := &ccprovider.ChaincodeData{Name: cds.ChaincodeSpec.ChaincodeId.Name, Version: cds.ChaincodeSpec.ChaincodeId.Version, ...} Defensive patterns
Strategy: validation
Validate before calling
// before submit: ensure lscc ChaincodeData name matches the spec
cd := &ccprovider.ChaincodeData{}
proto.Unmarshal(lsccWriteValue, cd)
if cd.Name != cds.ChaincodeSpec.ChaincodeId.Name {
return fmt.Errorf("proposal name %s != lscc record name %s", cds.ChaincodeSpec.ChaincodeId.Name, cd.Name)
} Type guard
func nameMatches(cd *ccprovider.ChaincodeData, specName string) bool { return cd != nil && cd.Name == specName } Try / catch
if err != nil && strings.Contains(err.Error(), "expected cc name") { /* regenerate the deploy/upgrade proposal with correct name */ } Prevention
- Derive ChaincodeData fields from the same ChaincodeSpec used in the proposal
- Do not reuse serialized ChaincodeData across chaincodes
- Label and store signed proposals by chaincode name to avoid replay mix-ups
When it happens
Trigger: A deploy/upgrade transaction for chaincode A whose lscc write-set value contains ChaincodeData with Name B — typically from a hand-modified proposal, replayed transaction, or tampered rwset.
Common situations: Reusing a serialized ChaincodeData blob from a previous deployment of a different chaincode, custom lifecycle scripts mixing up name fields, replaying an old proposal after renaming the chaincode, malicious transaction tampering.
Related errors
- malformed chaincode invocation spec
- No read write set for lscc was found
- expected key %s, found %s
- expected cc name %s, found %s
- expected cc version %s, found %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/49229c48d8973112.
Report an issue: GitHub.