{"record":{"id":"b8d8562bd58880f1","repo":"hyperledger/fabric","slug":"expected-endorsementplugin-s-does-not-match-pas","errorCode":null,"errorMessage":"expected EndorsementPlugin '%s' does not match passed EndorsementPlugin '%s'","messagePattern":"expected EndorsementPlugin '(.+?)' does not match passed EndorsementPlugin '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/chaincode/lifecycle/lifecycle.go","lineNumber":128,"sourceCode":"\tPackageID string\n}\n\n// ChaincodeParameters are the parts of the chaincode definition which are serialized\n// as values in the statedb.  It is expected that any instance will have no nil fields once initialized.\n// WARNING: This structure is serialized/deserialized from the DB, re-ordering or adding fields\n// will cause opaque checks to fail.\ntype ChaincodeParameters struct {\n\tEndorsementInfo *lb.ChaincodeEndorsementInfo\n\tValidationInfo  *lb.ChaincodeValidationInfo\n\tCollections     *pb.CollectionConfigPackage\n}\n\nfunc (cp *ChaincodeParameters) Equal(ocp *ChaincodeParameters) error {\n\tswitch {\n\tcase cp.EndorsementInfo.Version != ocp.EndorsementInfo.Version:\n\t\treturn errors.Errorf(\"expected Version '%s' does not match passed Version '%s'\", cp.EndorsementInfo.Version, ocp.EndorsementInfo.Version)\n\tcase cp.EndorsementInfo.EndorsementPlugin != ocp.EndorsementInfo.EndorsementPlugin:\n\t\treturn errors.Errorf(\"expected EndorsementPlugin '%s' does not match passed EndorsementPlugin '%s'\", cp.EndorsementInfo.EndorsementPlugin, ocp.EndorsementInfo.EndorsementPlugin)\n\tcase cp.EndorsementInfo.InitRequired != ocp.EndorsementInfo.InitRequired:\n\t\treturn errors.Errorf(\"expected InitRequired '%t' does not match passed InitRequired '%t'\", cp.EndorsementInfo.InitRequired, ocp.EndorsementInfo.InitRequired)\n\tcase cp.ValidationInfo.ValidationPlugin != ocp.ValidationInfo.ValidationPlugin:\n\t\treturn errors.Errorf(\"expected ValidationPlugin '%s' does not match passed ValidationPlugin '%s'\", cp.ValidationInfo.ValidationPlugin, ocp.ValidationInfo.ValidationPlugin)\n\tcase !bytes.Equal(cp.ValidationInfo.ValidationParameter, ocp.ValidationInfo.ValidationParameter):\n\t\treturn errors.Errorf(\"expected ValidationParameter '%x' does not match passed ValidationParameter '%x'\", cp.ValidationInfo.ValidationParameter, ocp.ValidationInfo.ValidationParameter)\n\tcase !proto.Equal(cp.Collections, ocp.Collections):\n\t\treturn errors.Errorf(\"Collections do not match\")\n\tdefault:\n\t}\n\treturn nil\n}\n\n// ChaincodeDefinition contains the chaincode parameters, as well as the sequence number of the definition.\n// Note, it does not embed ChaincodeParameters so as not to complicate the serialization.  It is expected\n// that any instance will have no nil fields once initialized.\n// WARNING: This structure is serialized/deserialized from the DB, re-ordering or adding fields\n// will cause opaque checks to fail.","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/chaincode/lifecycle/lifecycle.go#L110-L146","documentation":"Thrown by ChaincodeParameters.Equal when the EndorsementPlugin field of the new chaincode definition differs from the committed one. Lifecycle forbids silently changing which endorsement plugin a chaincode uses between definitions at the same sequence.","triggerScenarios":"Committing or redefining a chaincode whose EndorsementInfo.EndorsementPlugin differs from the already-committed definition; comparison invoked from isAttemptToRedefine or CommitChaincodeDefinition.","commonSituations":"Switching from the default 'escc' to a custom endorsement plugin without bumping sequence; one org approved with 'escc' while another approved a different plugin name and the reconciled definition differs.","solutions":["Keep the EndorsementPlugin identical to the committed definition, or increase the sequence number to intentionally change it","Verify the plugin name spelling against the peer's core.yaml endorsementPlugins configuration","Re-approve the definition on all orgs with a consistent EndorsementPlugin value"],"exampleFix":"// before\nEndorsementPlugin: 'my-custom-escc', sequence: 1 // committed uses 'escc'\n// after\nEndorsementPlugin: 'escc', sequence: 1 // or sequence: 2 to legitimately change plugins","handlingStrategy":"validation","validationCode":"committed, err := lifecycle.QueryChaincodeDefinition(chname, ccname, publicState)\nif err == nil && newDef.EndorsementInfo.EndorsementPlugin != committed.EndorsementInfo.EndorsementPlugin && newDef.Sequence == committed.Sequence {\n    return fmt.Errorf(\"endorsement plugin change requires sequence bump\")\n}","typeGuard":"func sameEndorsementPlugin(a, b *lifecycle.ChaincodeParameters) bool {\n    return a != nil && b != nil && a.EndorsementInfo.EndorsementPlugin == b.EndorsementInfo.EndorsementPlugin\n}","tryCatchPattern":"if err := params.Equal(committedParams); err != nil {\n    var expected string\n    if strings.Contains(err.Error(), \"EndorsementPlugin\") {\n        // fall back to committed plugin name or bump sequence\n    }\n    return err\n}","preventionTips":["Stick to the default 'escc' unless a custom plugin is deliberately deployed","Verify custom plugin names are registered in peer core.yaml before approval","Use identical approval payloads across all organizations"],"tags":["hyperledger-fabric","lifecycle","endorsement-plugin","definition-mismatch"],"backgroundTag":"chaincode-definition-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"}