hyperledger/fabric · error
expected cc version %s, found %s
Error message
expected cc version %s, found %s
What it means
The validator compares the Version in the ChaincodeData produced by lscc against the Version in the submitted ChaincodeDeploymentSpec. If they differ, the write-set does not faithfully reflect the deployment spec and the transaction fails validation. This prevents an attacker from deploying one version while recording another on the ledger.
Source
Thrown at core/handlers/validation/builtin/v13/lscc_validation_logic.go:479
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:
/******************************************************************/
/* security check 1 - cc not in the LCCC table of instantiated cc */
/******************************************************************/
if ccExistsOnLedger {
return policyErr(fmt.Errorf("Chaincode %s is already instantiated", cdsArgs.ChaincodeSpec.ChaincodeId.Name))View on GitHub (pinned to 2736b63f8f)
Solutions
- Regenerate the upgrade proposal with the correct, matching version in both ChaincodeSpec.ChaincodeId.Version and the lscc write value.
- If using custom code, construct ChaincodeData.Version from cds.ChaincodeSpec.ChaincodeId.Version.
- Discard cached signed proposals after changing the chaincode version.
- Verify the chaincode package/version used by install and instantiate steps is the same.
Example fix
// before
cd := &ccprovider.ChaincodeData{Name: name, Version: "1.0", ...}
// after
cd := &ccprovider.ChaincodeData{Name: cds.ChaincodeSpec.ChaincodeId.Name, Version: cds.ChaincodeSpec.ChaincodeId.Version, ...} Defensive patterns
Strategy: validation
Validate before calling
// before submit: version in spec must equal version in lscc record
cd := &ccprovider.ChaincodeData{}
proto.Unmarshal(lsccWriteValue, cd)
if cd.Version != cds.ChaincodeSpec.ChaincodeId.Version {
return fmt.Errorf("spec version %s != lscc record version %s", cds.ChaincodeSpec.ChaincodeId.Version, cd.Version)
} Type guard
func versionMatches(cd *ccprovider.ChaincodeData, specVersion string) bool { return cd != nil && cd.Version == specVersion } Try / catch
if err != nil && strings.Contains(err.Error(), "expected cc version") { /* rebuild proposal with matching version and resubmit */ } Prevention
- Bump version in one place and propagate it to spec, package, and proposal
- Discard cached signed proposals after version changes
- Parameterize versions in deployment scripts
When it happens
Trigger: An upgrade transaction where the new version in ChaincodeSpec.ChaincodeId.Version does not equal the Version serialized into the lscc ChaincodeData write — e.g. a stale or mismatched proposal.
Common situations: Custom lifecycle tooling hard-coding version "1.0" while the spec says "2.0", reusing an old signed proposal after bumping the version, SDK builds the ChaincodeData from different metadata than the spec, replaying a previous upgrade transaction.
Related errors
- Upgrading non-existent chaincode %s
- Existing version of the cc on the ledger (%s) should be diff
- unmarshalling of ChaincodeData failed, error %s
- expected cc name %s, found %s
- Existing version of the cc on the ledger (%s) should be diff
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/b8828b478e80ae82.
Report an issue: GitHub.