{"record":{"id":"9fde5c80e4e79629","repo":"hyperledger/fabric","slug":"expected-validationplugin-s-does-not-match-pass","errorCode":null,"errorMessage":"expected ValidationPlugin '%s' does not match passed ValidationPlugin '%s'","messagePattern":"expected ValidationPlugin '(.+?)' does not match passed ValidationPlugin '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/chaincode/lifecycle/lifecycle.go","lineNumber":132,"sourceCode":"// 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.\ntype ChaincodeDefinition struct {\n\tSequence        int64\n\tEndorsementInfo *lb.ChaincodeEndorsementInfo\n\tValidationInfo  *lb.ChaincodeValidationInfo","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/chaincode/lifecycle/lifecycle.go#L114-L150","documentation":"Thrown by ChaincodeParameters.Equal when the ValidationPlugin field of the new definition differs from the committed one. Lifecycle rejects changing the validation plugin (default 'vscc') for the same sequence number.","triggerScenarios":"Committing/redefining a chaincode whose ValidationInfo.ValidationPlugin differs from the committed definition, via CheckCommitReadiness/CommitChaincodeDefinition comparison paths.","commonSituations":"Switching to a custom state-based validation plugin without incrementing sequence; mismatched approvals where orgs approved different plugin names.","solutions":["Use the same ValidationPlugin as the committed definition, or increment the sequence number","Confirm the plugin is registered in the peer's validators configuration","Align all org approvals on one ValidationPlugin value before committing"],"exampleFix":"// before\nValidationPlugin: 'custom-vscc', sequence: 1 // committed uses 'vscc'\n// after\nValidationPlugin: 'vscc', sequence: 1 // or sequence: 2 to change plugins intentionally","handlingStrategy":"validation","validationCode":"committed, err := lifecycle.QueryChaincodeDefinition(chname, ccname, publicState)\nif err == nil && newDef.ValidationInfo.ValidationPlugin != committed.ValidationInfo.ValidationPlugin && newDef.Sequence == committed.Sequence {\n    return fmt.Errorf(\"validation plugin change requires sequence bump\")\n}","typeGuard":"func sameValidationPlugin(a, b *lifecycle.ChaincodeParameters) bool {\n    return a != nil && b != nil && a.ValidationInfo.ValidationPlugin == b.ValidationInfo.ValidationPlugin\n}","tryCatchPattern":"if err := params.Equal(committedParams); err != nil {\n    if strings.Contains(err.Error(), \"ValidationPlugin\") {\n        // reuse committed plugin or bump sequence\n    }\n    return err\n}","preventionTips":["Use the default 'vscc' unless a custom validator is intentionally deployed","Confirm custom validator names exist in peer configuration before approval","Keep approvals byte-identical across organizations"],"tags":["hyperledger-fabric","lifecycle","validation-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"}