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

  1. Resubmit the deploy/upgrade ensuring the ChaincodeSpec chaincode name matches the name passed to lscc.
  2. Do not modify the proposal payload after endorsement (invalidates signature and consistency).
  3. Use a current SDK to build the instantiate/upgrade request with a single consistent chaincodeId.
  4. 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

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


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