{"record":{"id":"3c7b4ed8e539a83b","repo":"hyperledger/fabric","slug":"expected-validationparameter-x-does-not-match-p","errorCode":null,"errorMessage":"expected ValidationParameter '%x' does not match passed ValidationParameter '%x'","messagePattern":"expected ValidationParameter '%x' does not match passed ValidationParameter '%x'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/chaincode/lifecycle/lifecycle.go","lineNumber":134,"sourceCode":"// 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\n\tCollections     *pb.CollectionConfigPackage\n}","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/chaincode/lifecycle/lifecycle.go#L116-L152","documentation":"Thrown by ChaincodeParameters.Equal when the ValidationParameter bytes (the endorsement policy / validation parameter) of the new definition differ from the committed definition, compared with bytes.Equal.","triggerScenarios":"Committing a definition whose --endorsement-policy or --signature-policy bytes differ from the committed one at the same sequence; redefine comparison in lifecycle.","commonSituations":"Changing the endorsement policy between approvals without bumping sequence; policy expressed with different (but non-identical) JSON that serializes to different bytes; org approvals disagreeing on policy.","solutions":["Pass the identical validation/endorsement policy bytes as the committed definition, or bump the sequence number","Inspect the committed policy via 'peer lifecycle chaincode querycommitted' and reuse that exact policy specification","Re-approve on all orgs with the same endorsement policy before committing"],"exampleFix":"// before\n--signature-policy \"AND('Org1.peer','Org2.peer')\", sequence: 1 // committed policy was OR(...)\n// after\n--signature-policy \"OR('Org1.peer','Org2.peer')\", sequence: 1 // match, or use sequence: 2 to change","handlingStrategy":"validation","validationCode":"committed, err := lifecycle.QueryChaincodeDefinition(chname, ccname, publicState)\nif err == nil && !bytes.Equal(newDef.ValidationInfo.ValidationParameter, committed.ValidationInfo.ValidationParameter) && newDef.Sequence == committed.Sequence {\n    return fmt.Errorf(\"validation parameter change requires sequence bump\")\n}","typeGuard":"func sameValidationParameter(a, b *lifecycle.ChaincodeParameters) bool {\n    return a != nil && b != nil && bytes.Equal(a.ValidationInfo.ValidationParameter, b.ValidationInfo.ValidationParameter)\n}","tryCatchPattern":"if err := params.Equal(committedParams); err != nil {\n    if strings.Contains(err.Error(), \"ValidationParameter\") {\n        // reuse the committed policy bytes or bump sequence\n    }\n    return err\n}","preventionTips":["Store the endorsement policy specification in version control and reuse it verbatim","Avoid reformatting policy JSON between approvals — bytes must match","Re-approve all orgs whenever the policy changes, with sequence+1"],"tags":["hyperledger-fabric","lifecycle","validation-parameter","endorsement-policy"],"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"}