hyperledger/fabric · error
LSCC can only issue a single putState upon upgrade
Error message
LSCC can only issue a single putState upon upgrade
What it means
Mirror of the deploy check on the UPGRADE path: when private channel data handling is not in effect, lscc's write-set must contain exactly one write (the updated ChaincodeData). Any other number of writes means the upgrade rwset deviates from the expected contract and the transaction fails validation.
Source
Thrown at core/handlers/validation/builtin/v13/lscc_validation_logic.go:561
/**********************************************************/
if cdLedger.Version == cdsArgs.ChaincodeSpec.ChaincodeId.Version {
return policyErr(fmt.Errorf("Existing version of the cc on the ledger (%s) should be different from the upgraded one", cdsArgs.ChaincodeSpec.ChaincodeId.Version))
}
/****************************************************************************/
/* security check 3 validation of rwset (and of collections if enabled) */
/****************************************************************************/
// Only in v1.2, a collection can be updated during a chaincode upgrade
if ac.V1_2Validation() {
// do extra validation for collections
err := vscc.validateRWSetAndCollection(lsccrwset, cdRWSet, lsccArgs, lsccFunc, ac, chid)
if err != nil {
return err
}
} else {
// there can only be a single ledger write
if len(lsccrwset.Writes) != 1 {
return policyErr(fmt.Errorf("LSCC can only issue a single putState upon upgrade"))
}
}
/*****************************************************/
/* security check 4 - check the instantiation policy */
/*****************************************************/
pol := cdLedger.InstantiationPolicy
if pol == nil {
return policyErr(fmt.Errorf("No instantiation policy was specified"))
}
// FIXME: could we actually pull the cds package from the
// file system to verify whether the policy that is specified
// here is the same as the one on disk?
// PROS: we prevent attacks where the policy is replaced
// CONS: this would be a point of non-determinism
err := vscc.checkInstantiationPolicy(chid, env, pol, payl)
if err != nil {
return errView on GitHub (pinned to 2736b63f8f)
Solutions
- Use the stock lscc so the upgrade writes exactly one updated ChaincodeData record.
- Remove extra putState calls from any patched upgrade path or move them into separate transactions.
- For hand-built test rwsets, provide exactly one lscc write with a valid ChaincodeData value.
- Align the private-channel-data (V1.2 collection capability) setting across all channel peers if collection updates during upgrade are intended.
Example fix
// before (custom lscc upgrade)
stub.PutState(ccname, cdBytes)
stub.PutState("upgrade-log", logBytes) // extra
// after
stub.PutState(ccname, cdBytes) // exactly one write Defensive patterns
Strategy: validation
Validate before calling
// pre-flight on upgrade rwsets
if n := countWrites(nsRwSet["lscc"]); n != 1 {
return fmt.Errorf("lscc upgrade must write exactly 1 key, got %d", n)
} Type guard
func isSingleUpgradeWrite(ns *rwset.NsRwSet) bool { return ns != nil && len(ns.KvRwSet.Writes) == 1 } Try / catch
if err != nil && strings.Contains(err.Error(), "single putState upon upgrade") { /* remove extra writes or run stock lscc and retry */ } Prevention
- Use stock lscc for upgrades
- Move supplementary writes out of the upgrade transaction
- Align private-channel-data capability settings across peers
When it happens
Trigger: An lscc upgrade whose lscc-namespaced rwset has 0 or 2+ writes — produced by a modified lscc, fabricated test rwsets, or extra putState calls added to the upgrade flow.
Common situations: Custom lscc forks writing supplementary keys during upgrade, unit/integration tests composing upgrade rwsets by hand, a collection-update flow run against peers whose PrivateChannelData() capability is off.
Related errors
- No read write set for lscc was found
- LSCC must issue at least one single putState upon deploy/upg
- 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
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/749e54d93402090a.
Report an issue: GitHub.