hyperledger/fabric · error · VSCCEndorsementPolicyError
LSCC must issue at least one single putState upon deploy/upg
Error message
LSCC must issue at least one single putState upon deploy/upgrade
What it means
A deploy/upgrade of a chaincode must cause lscc to write at least one key to the ledger (the ChaincodeData record). If the lscc rwset exists but has zero writes, the validator rejects the transaction because no chaincode registration actually occurred.
Source
Thrown at core/handlers/validation/builtin/v12/validation_logic.go:603
}
}
// retrieve from the ledger the entry for the chaincode at hand
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))View on GitHub (pinned to 2736b63f8f)
Solutions
- Re-run instantiation through the official SDK/lifecycle so lscc issues its putState of ChaincodeData.
- Check lscc is unmodified (stock system chaincode) on all peers.
- Align peer binary and validation plugin versions (v12 validator expects lscc write semantics).
- Decode the transaction rwset to confirm lscc has >=1 write before resubmitting.
Defensive patterns
Strategy: validation
Validate before calling
ns := rwSet.GetNsRwSet("lscc")
if ns == nil || len(ns.KvRwSet.Writes) < 1 {
return fmt.Errorf("lscc must write ChaincodeData; regenerate the deploy transaction")
} Type guard
func lsccHasWrites(txRWSet *rwset.TxRwSet) bool {
ns := txRWSet.GetNsRwSet("lscc")
return ns != nil && len(ns.KvRwSet.Writes) >= 1
} Try / catch
if err := submitTx(envelope); err != nil {
if strings.Contains(err.Error(), "must issue at least one single putState") {
// re-run instantiate via official SDK / stock lscc
}
} Prevention
- Use unmodified stock lscc
- Avoid custom lscc patches that skip putState
- Keep Fabric peer versions uniform across the network
When it happens
Trigger: Invoking lscc deploy/upgrade where lscc returns without calling putState, e.g. lscc code path short-circuits, or the rwset contains only reads for lscc.
Common situations: Custom-patched lscc; chaincode instantiated via deprecated/manual flows; rwset generated by a simulation that skipped lscc writes; version skew between peer validation code (v12) and lscc behavior.
Related errors
- No read write set for lscc was found
- LSCC invocation is attempting to write to namespace %s
- LSCC can only issue a single putState upon upgrade
- LSCC can only issue one or two putState upon deploy
- LSCC invocation is attempting to write to namespace %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/623b71aeb701ee3f.
Report an issue: GitHub.