{"record":{"id":"41bdc4acd25a1d82","repo":"hyperledger/fabric","slug":"policy-for-s-not-satisfied","errorCode":null,"errorMessage":"policy for %s not satisfied","messagePattern":"policy for (.+?) not satisfied","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/configtx/update.go","lineNumber":99,"sourceCode":"\t\t\tif value.version() != 0 {\n\t\t\t\treturn errors.Errorf(\"attempted to set key %s to version %d, but key does not exist\", key, value.version())\n\t\t\t}\n\n\t\t\tcontinue\n\t\t}\n\t\tif value.version() != existing.version()+1 {\n\t\t\treturn errors.Errorf(\"attempt to set key %s to version %d, but key is at version %d\", key, value.version(), existing.version())\n\t\t}\n\n\t\tpolicy, ok := vi.policyForItem(existing)\n\t\tif !ok {\n\t\t\treturn errors.Errorf(\"unexpected missing policy %s for item %s\", existing.modPolicy(), key)\n\t\t}\n\n\t\t// Ensure the policy is satisfied\n\t\tif err := policy.EvaluateSignedData(signedData); err != nil {\n\t\t\tlogger.Warnw(\"policy not satisfied for channel configuration update\", \"key\", key, \"policy\", policy, \"signingIdenties\", protoutil.LogMessageForSerializedIdentities(signedData))\n\t\t\treturn errors.Wrapf(err, \"policy for %s not satisfied\", key)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc verifyFullProposedConfig(writeSet, fullProposedConfig map[string]comparable) error {\n\tfor key := range writeSet {\n\t\tif _, ok := fullProposedConfig[key]; !ok {\n\t\t\treturn errors.Errorf(\"writeset contained key %s which did not appear in proposed config\", key)\n\t\t}\n\t}\n\treturn nil\n}\n\n// authorizeUpdate validates that all modified config has the corresponding modification policies satisfied by the signature set\n// it returns a map of the modified config\nfunc (vi *ValidatorImpl) authorizeUpdate(configUpdateEnv *cb.ConfigUpdateEnvelope) (map[string]comparable, error) {\n\tif configUpdateEnv == nil {","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/configtx/update.go#L81-L117","documentation":"verifyDeltaSet rejected the config update because the modification policy for a changed key evaluated the supplied signatures and they did not satisfy it. EvaluateSignedData failed, so the update lacks valid signatures from identities authorized by the item's mod_policy. The wrapped error contains the underlying policy evaluation failure.","triggerScenarios":"Calling proposeConfigUpdate or Validate with a ConfigUpdateEnvelope whose writeSet changes keys (adds/updates/removes) whose mod_policy is not satisfied by the signatures in the envelope's signatures field.","commonSituations":"Submitting an organization-level config change without collecting signatures from the required org admins; missing one org's signature in a multi-org channel; signatures from stale certificates after MSP cert rotation; insufficient signature count for a Majority/Any policy.","solutions":["Collect signatures from identities satisfying the mod_policy of every changed key (typically org Admins) and add them to the ConfigUpdateEnvelope.","Check the wrapped error to see which policy failed and which key; verify the signing identities belong to the right MSP.","Ensure certificates used to sign are current (not expired/revoked) and match the MSP config in the channel.","If the change is unintentional, remove the key from the writeSet so its policy is not evaluated.","Use `peer channel signconfigtx` for each required org before submitting."],"exampleFix":"// before: submitting update with no/insufficient signatures\nconfigUpdateEnv.Signatures = nil\n// after: sign with an identity satisfying the mod_policy\nsignedEnv, _ := protoutil.CreateSignedEnvelope(...)\nsignedEnv, _ := utils.SignEnvelope(signedEnv, mspID, signer)\n// or: peer channel signconfigtx -f update.pb","handlingStrategy":"try-catch","validationCode":"// Pre-check signatures cover the required admin policies before submitting\nfunc sufficientSigs(env *cb.ConfigUpdateEnvelope, required int) bool {\n    return len(env.GetSignatures()) >= required\n}","typeGuard":null,"tryCatchPattern":"if _, err := validator.ProposeConfigUpdate(env, seq); err != nil {\n    if strings.Contains(err.Error(), \"policy for \") && strings.Contains(err.Error(), \"not satisfied\") {\n        // gather additional admin signatures and re-sign the envelope\n        return fmt.Errorf(\"collect signatures from org admins for changed keys: %w\", err)\n    }\n    return err\n}","preventionTips":["Use `peer channel signconfigtx` for every org whose Admins policy covers a changed key before submitting.","Diff the update first and list each changed key's mod_policy to build a signature checklist.","Rotate MSP certificates proactively; expired admin certs are a top cause of failed policy evaluation.","For Majority policies, compute the required org count before collecting signatures."],"tags":["hyperledger-fabric","configtx","policy","signature"],"backgroundTag":"policy-not-satisfied","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"}