{"record":{"id":"90f5e8e7150ee719","repo":"slackhq/nebula","slug":"unable-to-find-host","errorCode":null,"errorMessage":"unable to find host","messagePattern":"unable to find host","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"hostmap.go","lineNumber":598,"sourceCode":"\t} else {\n\t\thm.RUnlock()\n\t\treturn nil\n\t}\n}\n\nfunc (hm *HostMap) QueryVpnAddr(vpnIp netip.Addr) *HostInfo {\n\treturn hm.queryVpnAddr(vpnIp, nil)\n}\n\nfunc (hm *HostMap) QueryVpnAddrsRelayFor(targetIps []netip.Addr, relayHostIp netip.Addr) (*HostInfo, *Relay, error) {\n\thm.RLock()\n\tdefer hm.RUnlock()\n\n\t// This runs per relayed packet, so check the primary with a single map probe and only consult\n\t// moreHosts when the primary can't relay for us.\n\th, ok := hm.Hosts[relayHostIp]\n\tif !ok {\n\t\treturn nil, nil, errors.New(\"unable to find host\")\n\t}\n\n\tfor _, targetIp := range targetIps {\n\t\tr, ok := h.relayState.QueryRelayForByIp(targetIp)\n\t\tif ok && r.State == Established {\n\t\t\treturn h, r, nil\n\t\t}\n\t}\n\n\tif list, ok := hm.moreHosts[relayHostIp]; ok {\n\t\t// list[0] is the primary we already checked\n\t\tfor _, h := range list[1:] {\n\t\t\tfor _, targetIp := range targetIps {\n\t\t\t\tr, ok := h.relayState.QueryRelayForByIp(targetIp)\n\t\t\t\tif ok && r.State == Established {\n\t\t\t\t\treturn h, r, nil\n\t\t\t\t}\n\t\t\t}","sourceCodeStart":580,"sourceCodeEnd":616,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/hostmap.go#L580-L616","documentation":"HostMap.QueryRelayForByIpVpnAddr (hostmap.go) looks up the relay host by its IP in hm.Hosts and then queries that host's relay state for an established relay to the target. This error is returned when the given relayHostIp has no entry in the HostMap at all, so no relayed route can be resolved for the packet.","triggerScenarios":"A relayed packet arrives/is relayed with a relayHostIp that was never added to the HostMap, or the host entry was evicted/expired (dead host pruning) between relay establishment and this packet.","commonSituations":"Relay host disconnected or its host entry aged out while other peers still hold relay state pointing at it; misconfigured relay IP in relay setup; packet race during host teardown.","solutions":["Verify the relay host is connected and present in the hostmap (check nebula logs for the relay host's handshake)","Re-establish the tunnel/relay so the host entry is re-added","Check for host-entry expiry settings or aggressive pruning affecting the relay host","Ensure both peers run compatible nebula versions supporting relays"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before relying on relays, confirm the relay host exists\nhm.RLock()\n_, ok := hm.Hosts[relayHostIp]\nhm.RUnlock()\nif !ok { /* re-handshake with relay host or fall back to direct path */ }","typeGuard":null,"tryCatchPattern":"if _, _, err := hm.QueryRelayForByIpVpnAddr(relayHostIp, targetIps); err != nil && err.Error() == \"unable to find host\" { /* fall back to direct handshake */ }","preventionTips":["Monitor relay host liveness and prune relay state when the relay host expires","Re-handshake promptly when relay errors appear","Keep nebula versions consistent across relay and relayed hosts"],"tags":["network","relay","hostmap","nebula"],"backgroundTag":"relay-host-not-found","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}