{"record":{"id":"6079daef43c13720","repo":"hyperledger/fabric","slug":"timeout-should-be-specified","errorCode":null,"errorMessage":"Timeout should be specified","messagePattern":"Timeout should be specified","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gossip/gossip/gossip_impl.go","lineNumber":631,"sourceCode":"\t\tif msg.filter(peer.PKIID) {\n\t\t\tresult = append(result, peer)\n\t\t}\n\t}\n\treturn result\n}\n\n// IdentityInfo returns information known peer identities\nfunc (g *Node) IdentityInfo() api.PeerIdentitySet {\n\treturn g.idMapper.IdentityInfo()\n}\n\n// SendByCriteria sends a given message to all peers that match the given SendCriteria\nfunc (g *Node) SendByCriteria(msg *protoext.SignedGossipMessage, criteria SendCriteria) error {\n\tif criteria.MaxPeers == 0 {\n\t\treturn nil\n\t}\n\tif criteria.Timeout == 0 {\n\t\treturn errors.New(\"Timeout should be specified\")\n\t}\n\n\tif criteria.IsEligible == nil {\n\t\tcriteria.IsEligible = filter.SelectAllPolicy\n\t}\n\n\tmembership := g.disc.GetMembership()\n\n\tif len(criteria.Channel) > 0 {\n\t\tgc := g.chanState.getGossipChannelByChainID(criteria.Channel)\n\t\tif gc == nil {\n\t\t\treturn fmt.Errorf(\"requested to Send for channel %s, but no such channel exists\", criteria.Channel)\n\t\t}\n\t\tmembership = gc.GetPeers()\n\t}\n\n\tpeers2send := filter.SelectPeers(criteria.MaxPeers, membership, criteria.IsEligible)\n\tif len(peers2send) < criteria.MinAck {","sourceCodeStart":613,"sourceCodeEnd":649,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/gossip/gossip/gossip_impl.go#L613-L649","documentation":"Gossip's SendByCriteria requires the SendCriteria to carry a non-zero Timeout, because it forwards the timeout to the underlying comm layer (SendWithAck) for ack-based delivery. A zero Timeout makes the send duration undefined, so the call is rejected immediately before any network activity.","triggerScenarios":"Calling Node.SendByCriteria with a SendCriteria literal that omits Timeout (zero value) while MaxPeers is non-zero — e.g. constructing criteria with only Channel/MaxPeers/MinAck set.","commonSituations":"Unit tests (TestSendByCriteria) or application code building SendCriteria structs where the Timeout field is forgotten or assumed to default to something sensible.","solutions":["Set criteria.Timeout to an explicit duration (e.g. time.Second * 5) before calling SendByCriteria","Derive the timeout from an existing config value (timeout ranges used elsewhere in gossip) instead of a zero literal","If you truly want fire-and-forget behavior, use a different send API rather than passing zero Timeout"],"exampleFix":"// before\nerr := g.SendByCriteria(msg, discovery.SendCriteria{Channel: chanID, MaxPeers: 3, MinAck: 2})\n\n// after\nerr := g.SendByCriteria(msg, discovery.SendCriteria{Channel: chanID, MaxPeers: 3, MinAck: 2, Timeout: 5 * time.Second})","handlingStrategy":"validation","validationCode":"if criteria.MaxPeers > 0 && criteria.Timeout == 0 {\n    return errors.New(\"SendCriteria.Timeout must be set\")\n}\nerr := g.SendByCriteria(msg, criteria)","typeGuard":null,"tryCatchPattern":"if err := g.SendByCriteria(msg, criteria); err != nil && strings.Contains(err.Error(), \"Timeout should be specified\") {\n    criteria.Timeout = 5 * time.Second\n    err = g.SendByCriteria(msg, criteria)\n}","preventionTips":["Always set Timeout in SendCriteria literals; make a constructor helper that enforces it","Use a shared default timeout constant in your codebase","Enable linters that flag zero-value time.Duration usage"],"tags":["gossip","hyperledger-fabric","misconfiguration"],"backgroundTag":"missing-required-argument","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"}