hyperledger/fabric · error · VSCCEndorsementPolicyError
Endorsement policy evaluation failure might be caused by dup
Error message
Endorsement policy evaluation failure might be caused by duplicated identities
What it means
When the endorsement policy evaluation fails AND the constructed signature set is smaller than the number of endorsements in the transaction, VSCC concludes that some endorsements carried duplicated identities (which were deduplicated away) and reports this dedicated error instead of the generic policy failure. The transaction is then marked invalid by the policy check.
Source
Thrown at core/handlers/validation/builtin/v12/validation_logic.go:163
cap, err := protoutil.UnmarshalChaincodeActionPayload(tx.Actions[actionPosition].Payload)
if err != nil {
logger.Errorf("VSCC error: GetChaincodeActionPayload failed, err %s", err)
return policyErr(err)
}
signatureSet, err := vscc.deduplicateIdentity(cap)
if err != nil {
return policyErr(err)
}
// evaluate the signature set against the policy
err = vscc.policyEvaluator.Evaluate(policyBytes, signatureSet)
if err != nil {
logger.Warningf("Endorsement policy failure for transaction txid=%s, err: %s", chdr.GetTxId(), err.Error())
if len(signatureSet) < len(cap.Action.Endorsements) {
// Warning: duplicated identities exist, endorsement failure might be cause by this reason
return policyErr(errors.New(DUPLICATED_IDENTITY_ERROR))
}
return policyErr(fmt.Errorf("VSCC error: endorsement policy failure, err: %s", err))
}
// do some extra validation that is specific to lscc
if namespace == "lscc" {
logger.Debugf("VSCC info: doing special validation for LSCC")
err := vscc.ValidateLSCCInvocation(chdr.ChannelId, env, cap, payl, vscc.capabilities)
if err != nil {
logger.Errorf("VSCC error: ValidateLSCCInvocation failed, err %s", err)
return err
}
}
return nil
}
// checkInstantiationPolicy evaluates an instantiation policy against a signed proposal.View on GitHub (pinned to 2736b63f8f)
Solutions
- Ensure each endorsement in the proposal response is from a distinct identity as required by the policy
- Fix client/SDK logic that re-signs and merges duplicate endorsements instead of requesting new signers
- If the policy is stricter than the number of available organizations, change the endorsement policy rather than duplicating signers
Example fix
// before // same identity signs twice, both endorsements appended endorsements = [sigFromOrgA, sigFromOrgA] // after // collect signatures from distinct endorsers per policy endorsements = [sigFromOrgA, sigFromOrgB]
Defensive patterns
Strategy: validation
Validate before calling
// client-side check before submitting
seen := map[string]bool{}
for _, e := range res.Action.Endorsements {
id := string(e.Endorser)
if seen[id] {
return fmt.Errorf("duplicate endorser identity: %s", id)
}
seen[id] = true
} Prevention
- Never append the same signer's endorsement twice when aggregating responses
- Ensure the endorsement policy requires at most as many orgs as you can collect
- Deduplicate by endorser identity when merging proposal responses from multiple peers
When it happens
Trigger: A transaction whose Action.Endorsements contain two or more endorsements from the SAME identity (same signer), so after dedup the signatureSet has fewer entries than endorsements, and the remaining signatures still fail policy evaluation.
Common situations: Misbehaving SDK or gateway retrying endorsement and appending the same signature twice; tests that sign twice with one identity while the policy expects N distinct signers; malicious peers padding endorsement counts with duplicate signatures.
Related errors
- VSCC error: endorsement policy failure, err: %s
- stateFetcher not passed in init
- Only Endorser Transactions are supported, provided type %d
- panic(err)
- config ID illegal, cannot be empty
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/24ff38273892ddaf.
Report an issue: GitHub.