{"record":{"id":"39131ec99526707f","repo":"canopy-network/canopy","slug":"invalid-dial-peer-s-s","errorCode":null,"errorMessage":"invalid dial peer %s: %s","messagePattern":"invalid dial peer (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"p2p/p2p.go","lineNumber":195,"sourceCode":"\t\t\tif err = p.AddPeer(c, &lib.PeerInfo{Address: &lib.PeerAddress{NetAddress: netAddress}}, false, false); err != nil {\n\t\t\t\tp.log.Error(err.Error())\n\t\t\t\t_ = c.Close()\n\t\t\t\treturn\n\t\t\t}\n\t\t}(c)\n\t}\n}\n\n// DialForOutboundPeers() uses the config and peer book to try to max out the outbound peer connections\nfunc (p *P2P) DialForOutboundPeers() {\n\t// create a tracking variable to ensure not 'over dialing'\n\tvar dialing atomic.Int32\n\tgetPeerFromString := func(address string) (*lib.PeerAddress, error) {\n\t\t// start a peer address structure using the basic configurations\n\t\tpeer := &lib.PeerAddress{PeerMeta: &lib.PeerMeta{NetworkId: p.meta.NetworkId, ChainId: p.meta.ChainId}}\n\t\t// try to populate the peer address using the peer string from the given string\n\t\tif err := peer.FromString(address); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid dial peer %s: %s\", address, err.Error())\n\t\t}\n\t\t// exit\n\t\treturn peer, nil\n\t}\n\t// Try to connect to the DialPeers in the config\n\tfor _, peerString := range p.config.DialPeers {\n\t\tpeerAddress, err := getPeerFromString(peerString)\n\t\tif err != nil {\n\t\t\t// log the invalid format\n\t\t\tp.log.Error(err.Error())\n\t\t\t// continue with the next\n\t\t\tcontinue\n\t\t}\n\t\t// dial in a non-blocking fashion\n\t\tgo func() {\n\t\t\t// increment dialing\n\t\t\tdialing.Add(1)\n\t\t\t// dial the peer with exponential backoff","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/canopy-network/canopy/blob/ee8197d91dd410f6592cb650a94c925ee6dc8bad/p2p/p2p.go#L177-L213","documentation":"When dialing statically configured peers, the node parses each configured peer string into a lib.PeerAddress via FromString. This error wraps any parse failure, identifying both the offending address string and the underlying reason (bad format, network/chain mismatch, etc.).","triggerScenarios":"Config field DialPeers contains a string that PeerAddress.FromString cannot parse — malformed multiaddr/peer string, wrong network ID or chain ID in the address, or empty/garbage entry in the config list.","commonSituations":"Typo in a dial peer address in config.json, copying a peer address from a different network (mainnet address on testnet config), stale peer strings after a protocol upgrade changed the address format.","solutions":["Check the wrapped inner error to see which part of the address failed (format vs network/chain ID)","Correct the peer address string in the DialPeers config to match the expected format and the node's NetworkId/ChainId","Obtain a fresh peer address string from the target peer's published address or another node on the same network","Remove stale entries from DialPeers if the peer is no longer available"],"exampleFix":"// before (config)\n\"dial_peers\": [\"/ip4/10.0.0.1/tcp{PORT}/p2p/BADID\"]\n// after\n\"dial_peers\": [\"/ip4/10.0.0.1/tcp5001/p2p/12D3KooWCorrectBase58ID\"]","handlingStrategy":"validation","validationCode":"if peerString == \"\" { return errors.New(\"empty dial peer\") }\nprobe := &lib.PeerAddress{PeerMeta: &lib.PeerMeta{NetworkId: expectedNet, ChainId: expectedChain}}\nif err := probe.FromString(peerString); err != nil {\n    return fmt.Errorf(\"config dial_peers entry %q invalid: %v\", peerString, err)\n}","typeGuard":"func isValidPeerAddress(s string, net, chain string) bool {\n    p := &lib.PeerAddress{PeerMeta: &lib.PeerMeta{NetworkId: net, ChainId: chain}}\n    return p.FromString(s) == nil\n}","tryCatchPattern":"peer, err := getPeerFromString(addr)\nif err != nil {\n    log.Warnf(\"skipping bad dial peer: %v\", err)\n    continue // or fail fast on startup, depending on policy\n}","preventionTips":["Validate the entire DialPeers list at config-load time, before starting the node","Copy peer strings only from nodes on the same network/chain ID","Keep peer addresses in version-controlled config and test them in CI","Re-fetch peer addresses after protocol upgrades"],"tags":["p2p","config","peer","dial"],"backgroundTag":"invalid-config-value","analyzedSha":"ee8197d91dd410f6592cb650a94c925ee6dc8bad","analyzedAt":"2026-09-06T09:30:15.973Z","contentChangedAt":"2026-09-06T09:30:15.973Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}