{"record":{"id":"0b4bc1e6758b007d","repo":"hyperledger/fabric","slug":"chaincode-s-s-s-didn-t-match-s-s-s-in-lscc","errorCode":null,"errorMessage":"chaincode %s:%s/%s didn't match %s:%s/%s in lscc","messagePattern":"chaincode (.+?):(.+?)/(.+?) didn't match (.+?):(.+?)/(.+?) in lscc","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/committer/txvalidator/v14/vscc_validator.go","lineNumber":204,"sourceCode":"\t\tif writesToNonInvokableSCC {\n\t\t\treturn peer.TxValidationCode_ILLEGAL_WRITESET,\n\t\t\t\terrors.Errorf(\"chaincode %s attempted to write to the namespace of a system chaincode that cannot be invoked\", ccID)\n\t\t}\n\n\t\t// validate *EACH* read write set according to its chaincode's endorsement policy\n\t\tfor _, ns := range wrNamespace {\n\t\t\t// Get latest chaincode version, vscc and validate policy\n\t\t\ttxcc, vscc, policy, err := v.GetInfoForValidate(chdr, ns)\n\t\t\tif err != nil {\n\t\t\t\tlogger.Errorf(\"GetInfoForValidate for txId = %s returned error: %+v\", chdr.TxId, err)\n\t\t\t\treturn peer.TxValidationCode_INVALID_OTHER_REASON, err\n\t\t\t}\n\n\t\t\t// if the namespace corresponds to the cc that was originally\n\t\t\t// invoked, we check that the version of the cc that was\n\t\t\t// invoked corresponds to the version that lscc has returned\n\t\t\tif ns == ccID && txcc.ChaincodeVersion != ccVer {\n\t\t\t\terr = errors.Errorf(\"chaincode %s:%s/%s didn't match %s:%s/%s in lscc\", ccID, ccVer, chdr.ChannelId, txcc.ChaincodeName, txcc.ChaincodeVersion, chdr.ChannelId)\n\t\t\t\tlogger.Errorf(\"%+v\", err)\n\t\t\t\treturn peer.TxValidationCode_EXPIRED_CHAINCODE, err\n\t\t\t}\n\n\t\t\t// do VSCC validation\n\t\t\tctx := &Context{\n\t\t\t\tSeq:       seq,\n\t\t\t\tEnvelope:  envBytes,\n\t\t\t\tBlock:     block,\n\t\t\t\tTxID:      chdr.TxId,\n\t\t\t\tChannel:   chdr.ChannelId,\n\t\t\t\tNamespace: ns,\n\t\t\t\tPolicy:    policy,\n\t\t\t\tVSCCName:  vscc.ChaincodeName,\n\t\t\t}\n\t\t\tif err = v.VSCCValidateTxForCC(ctx); err != nil {\n\t\t\t\tswitch err.(type) {\n\t\t\t\tcase *commonerrors.VSCCEndorsementPolicyError:","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/committer/txvalidator/v14/vscc_validator.go#L186-L222","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: resubmitting stale tx after upgrade\nconst tx = oldSignedTx; await gateway.submit(tx);\n// after: create a fresh proposal against the current version\nconst tx = await contract.createTransaction('move'); await tx.submit(args);","handlingStrategy":"retry","validationCode":"// check current instantiated version before submitting\nconst deployed = await channel.queryInstantiatedChaincodes();\nif (deployed.find(c => c.name === ccName).version !== expectedVersion) { /* abort or re-endorse */ }","typeGuard":"function matchesDeployedVersion(ccData, name, ver) {\n  return ccData && ccData.name === name && ccData.version === ver;\n}","tryCatchPattern":"try { await tx.submit(); } catch (e) {\n  if (String(e).includes('EXPIRED_CHAINCODE') || String(e).includes(\"didn't match\")) { /* re-create proposal against current version and retry once */ }\n}","preventionTips":["Quiesce traffic during chaincode upgrades","Confirm all peers run the same chaincode version","Re-create transactions rather than replaying stale signed ones after upgrades"],"tags":["hyperledger-fabric","chaincode","tx-validation","expired-chaincode","version-mismatch"],"backgroundTag":"chaincode-version-mismatch","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}