hyperledger/fabric · error
chaincode %s:%s/%s didn't match %s:%s/%s in lscc
Error message
chaincode %s:%s/%s didn't match %s:%s/%s in lscc
What it means
VSCC validation checks that the version of the chaincode recorded in the transaction matches the version lscc (lifecycle system chaincode) currently holds on the channel. When the invoked namespace equals the transaction's chaincode but its version differs from the lscc-recorded version, the transaction is marked EXPIRED_CHAINCODE. This prevents committing transactions produced against stale chaincode deployments.
Source
Thrown at core/committer/txvalidator/v14/vscc_validator.go:204
if writesToNonInvokableSCC {
return peer.TxValidationCode_ILLEGAL_WRITESET,
errors.Errorf("chaincode %s attempted to write to the namespace of a system chaincode that cannot be invoked", ccID)
}
// validate *EACH* read write set according to its chaincode's endorsement policy
for _, ns := range wrNamespace {
// Get latest chaincode version, vscc and validate policy
txcc, vscc, policy, err := v.GetInfoForValidate(chdr, ns)
if err != nil {
logger.Errorf("GetInfoForValidate for txId = %s returned error: %+v", chdr.TxId, err)
return peer.TxValidationCode_INVALID_OTHER_REASON, err
}
// if the namespace corresponds to the cc that was originally
// invoked, we check that the version of the cc that was
// invoked corresponds to the version that lscc has returned
if ns == ccID && txcc.ChaincodeVersion != ccVer {
err = errors.Errorf("chaincode %s:%s/%s didn't match %s:%s/%s in lscc", ccID, ccVer, chdr.ChannelId, txcc.ChaincodeName, txcc.ChaincodeVersion, chdr.ChannelId)
logger.Errorf("%+v", err)
return peer.TxValidationCode_EXPIRED_CHAINCODE, err
}
// do VSCC validation
ctx := &Context{
Seq: seq,
Envelope: envBytes,
Block: block,
TxID: chdr.TxId,
Channel: chdr.ChannelId,
Namespace: ns,
Policy: policy,
VSCCName: vscc.ChaincodeName,
}
if err = v.VSCCValidateTxForCC(ctx); err != nil {
switch err.(type) {
case *commonerrors.VSCCEndorsementPolicyError:View on GitHub (pinned to 2736b63f8f)
Solutions
- Re-submit the transaction after the chaincode upgrade completes so it is endorsed against the current version
- Coordinate upgrades to avoid in-flight transactions (drain/stop traffic during upgrade)
- Ensure all endorsing peers have the same chaincode version installed and instantiated
- Check lscc output (peer chaincode list) to confirm current version and align client expectations
Example fix
// before: resubmitting stale tx after upgrade
const tx = oldSignedTx; await gateway.submit(tx);
// after: create a fresh proposal against the current version
const tx = await contract.createTransaction('move'); await tx.submit(args); Defensive patterns
Strategy: retry
Validate before calling
// check current instantiated version before submitting
const deployed = await channel.queryInstantiatedChaincodes();
if (deployed.find(c => c.name === ccName).version !== expectedVersion) { /* abort or re-endorse */ } Type guard
function matchesDeployedVersion(ccData, name, ver) {
return ccData && ccData.name === name && ccData.version === ver;
} Try / catch
try { await tx.submit(); } catch (e) {
if (String(e).includes('EXPIRED_CHAINCODE') || String(e).includes("didn't match")) { /* re-create proposal against current version and retry once */ }
} Prevention
- Quiesce traffic during chaincode upgrades
- Confirm all peers run the same chaincode version
- Re-create transactions rather than replaying stale signed ones after upgrades
When it happens
Trigger: A transaction endorsed against chaincode version X is validated after the chaincode was upgraded to version Y via lscc (txcc.ChaincodeVersion != ccVer). Happens when a tx is signed/in flight during a chaincode upgrade.
Common situations: Chaincode upgrade performed while in-flight transactions are still being validated; endorsement by a peer running an old chaincode version; SDK retrying stale transactions after an upgrade.
Related errors
- chaincode %s attempted to write to the namespace of a system
- First message needs to be a register
- TLS is active but chaincode %s didn't send certificate
- Chaincode %s with given certificate hash %v not found in reg
- Chaincode %s with given certificate hash %v belongs to a dif
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/0b4bc1e6758b007d.
Report an issue: GitHub.