hyperledger/fabric · error · VSCCEndorsementPolicyError
expected key %s, found %s
Error message
expected key %s, found %s
What it means
The first key lscc writes must exactly equal the chaincode name declared in the deployment spec (ChaincodeSpec.ChaincodeId.Name). A mismatch means the rwset registers a different chaincode than the one the transaction claims to deploy, so validation fails as a policy error.
Source
Thrown at core/handlers/validation/builtin/v12/validation_logic.go:607
cdLedger, ccExistsOnLedger, err := vscc.getInstantiatedCC(chid, cdsArgs.ChaincodeSpec.ChaincodeId.Name)
if err != nil {
return &commonerrors.VSCCExecutionFailureError{Err: err}
}
/******************************************/
/* security check 0 - validation of rwset */
/******************************************/
// there has to be a write-set
if lsccrwset == nil {
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 {View on GitHub (pinned to 2736b63f8f)
Solutions
- Resubmit the deploy/upgrade ensuring the ChaincodeSpec chaincode name matches the name passed to lscc.
- Do not modify the proposal payload after endorsement (invalidates signature and consistency).
- Use a current SDK to build the instantiate/upgrade request with a single consistent chaincodeId.
- Verify the first lscc write key matches the intended chaincode before submission.
Example fix
// before
request.chaincodeId = 'mycc'
request.args = deployArgsFor('othercc') // mismatch
// after
request.chaincodeId = 'mycc'
request.args = deployArgsFor('mycc') Defensive patterns
Strategy: validation
Validate before calling
if ns.KvRwSet.Writes[0].Key != chaincodeSpec.ChaincodeId.Name {
return fmt.Errorf("lscc first write key %q does not match spec name %q", ns.KvRwSet.Writes[0].Key, chaincodeSpec.ChaincodeId.Name)
} Type guard
func firstWriteKeyMatches(ns *rwset.NsRwSet, name string) bool {
return ns != nil && len(ns.KvRwSet.Writes) > 0 && ns.KvRwSet.Writes[0].Key == name
} Try / catch
if err := submitTx(envelope); err != nil {
if strings.Contains(err.Error(), "expected key ") {
// rebuild proposal with a consistent chaincodeId; do not edit endorsed payloads
}
} Prevention
- Never modify proposal payloads after endorsement
- Use one chaincodeId consistently in the SDK request
- Avoid replaying envelopes across different deploy attempts
When it happens
Trigger: Transaction where lsccrwset.Writes[0].Key differs from cdsArgs.ChaincodeSpec.ChaincodeId.Name — e.g. spec tampered after endorsement, or rwset assembled out of order or from a different deploy invocation.
Common situations: Manually constructed or replayed envelopes; SDK bugs mixing chaincode names; upgrading chaincode A with a spec naming chaincode B; endorsement payload edited in transit.
Related errors
- expected cc name %s, found %s
- malformed chaincode invocation spec
- No read write set for lscc was found
- expected cc version %s, found %s
- expected cc name %s, found %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/625274062b474ad9.
Report an issue: GitHub.