{"record":{"id":"df6cb0eaedbe7e90","repo":"hyperledger/fabric","slug":"failed-disseminating-d-out-of-d-private-dissemin","errorCode":null,"errorMessage":"Failed disseminating %d out of %d private dissemination plans","messagePattern":"Failed disseminating (.+?) out of (.+?) private dissemination plans","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gossip/privdata/distributor.go","lineNumber":410,"sourceCode":"\tvar wg sync.WaitGroup\n\twg.Add(len(disseminationPlan))\n\tstart := time.Now()\n\tfor _, dis := range disseminationPlan {\n\t\tgo func(dis *dissemination) {\n\t\t\tdefer wg.Done()\n\t\t\tdefer d.reportSendDuration(start)\n\t\t\terr := d.SendByCriteria(dis.msg, dis.criteria)\n\t\t\tif err != nil {\n\t\t\t\tatomic.AddUint32(&failures, 1)\n\t\t\t\tm := dis.msg.GetPrivateData().Payload\n\t\t\t\td.logger.Error(\"Failed disseminating private RWSet for TxID\", m.TxId, \", namespace\", m.Namespace, \"collection\", m.CollectionName, \":\", err)\n\t\t\t}\n\t\t}(dis)\n\t}\n\twg.Wait()\n\tfailureCount := atomic.LoadUint32(&failures)\n\tif failureCount != 0 {\n\t\treturn errors.Errorf(\"Failed disseminating %d out of %d private dissemination plans\", failureCount, len(disseminationPlan))\n\t}\n\treturn nil\n}\n\nfunc (d *distributorImpl) reportSendDuration(startTime time.Time) {\n\td.metrics.SendDuration.With(\"channel\", d.chainID).Observe(time.Since(startTime).Seconds())\n}\n\nfunc (d *distributorImpl) createPrivateDataMessage(txID, namespace string,\n\tcollection *rwset.CollectionPvtReadWriteSet,\n\tccp *peer.CollectionConfigPackage,\n\tblkHt uint64,\n) (*protoext.SignedGossipMessage, error) {\n\tmsg := &protosgossip.GossipMessage{\n\t\tChannel: []byte(d.chainID),\n\t\tNonce:   util.RandomUInt64(),\n\t\tTag:     protosgossip.GossipMessage_CHAN_ONLY,\n\t\tContent: &protosgossip.GossipMessage_PrivateData{","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/gossip/privdata/distributor.go#L392-L428","documentation":"After dispatching all dissemination plans concurrently, disseminate counts send failures. If any plan failed to be sent to its designated peer(s), it returns this aggregate error so the caller (Distribute, used by the committer/gossip) knows private data dissemination was partial.","triggerScenarios":"One or more goroutines in disseminate fail to send their signed gossip message to the target peer (peer unreachable, connection error, rejected message), incrementing the atomic failure counter.","commonSituations":"Target peer down or network partition; TLS handshake failures between peers; message rejected because sender lacks access or channel mismatch. Note data may still be recoverable via reconciliation/pull from other peers.","solutions":["Check gossip logs on both sender and receiver for the underlying send failure","Ensure target peers are up, reachable, and TLS-configured correctly","Rely on private data reconciliation (reconciliationEnabled: true) to fetch missed data later; retry the commit flow"],"exampleFix":"// core.yaml\nprivateData:\n  reconciliationEnabled: true\n  (peer will pull missing private data later despite dissemination failure)","handlingStrategy":"retry","validationCode":"// pre-check connectivity\ncount := 0; for _, p := range plan.peers { if gossip.HasMembership(p) { count++ } }","typeGuard":null,"tryCatchPattern":"if err := distribute(...); err != nil {\n  if strings.Contains(err.Error(), \"Failed disseminating\") {\n    // enable/wait for reconciliation to recover missing pvtdata\n  }\n}","preventionTips":["Enable privateData.reconciliationEnabled in core.yaml","Keep inter-peer TLS and gossip anchors healthy"],"tags":["hyperledger-fabric","gossip","private-data","dissemination"],"backgroundTag":"private-data-dissemination-failed","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"}