{"record":{"id":"451fa0fb0c5c3490","repo":"slackhq/nebula","slug":"failed-to-generate-unique-localindexid","errorCode":null,"errorMessage":"failed to generate unique localIndexId","messagePattern":"failed to generate unique localIndexId","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"handshake_manager.go","lineNumber":527,"sourceCode":"\tdefer hm.Unlock()\n\n\tfor range 32 {\n\t\tindex, err := generateIndex(hm.l)\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\n\t\t_, inPending := hm.indexes[index]\n\t\t_, inMain := hm.mainHostMap.Indexes[index]\n\n\t\tif !inMain && !inPending {\n\t\t\thh.hostinfo.localIndexId = index\n\t\t\thm.indexes[index] = hh\n\t\t\treturn index, nil\n\t\t}\n\t}\n\n\treturn 0, errors.New(\"failed to generate unique localIndexId\")\n}\n\nfunc (hm *HandshakeManager) DeleteHostInfo(hostinfo *HostInfo) {\n\thm.Lock()\n\tdefer hm.Unlock()\n\thm.unlockedDeleteHostInfo(hostinfo)\n}\n\nfunc (hm *HandshakeManager) unlockedDeleteHostInfo(hostinfo *HostInfo) {\n\tfor _, addr := range hostinfo.vpnAddrs {\n\t\tif cur, ok := hm.vpnIps[addr]; ok && cur.hostinfo == hostinfo {\n\t\t\tdelete(hm.vpnIps, addr)\n\t\t}\n\t}\n\n\tif len(hm.vpnIps) == 0 {\n\t\thm.vpnIps = map[netip.Addr]*HandshakeHostInfo{}\n\t}","sourceCodeStart":509,"sourceCodeEnd":545,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/handshake_manager.go#L509-L545","documentation":"A non-sentinel error raised by HandshakeManager.allocateIndex when, after scanning candidate index values, it cannot find a localIndexId that is free in the indexes map. Means the local index space is effectively exhausted or heavily contended.","triggerScenarios":"allocateIndex (handshake_manager.go:527) iterating candidate indices finds every candidate already present in hm.indexes, so it returns errors.New(\"failed to generate unique localIndexId\").","commonSituations":"Index map leak — hostinfos never deleted via DeleteHostInfo so indexes accumulate; a massive handshake storm; a 32-bit/limited index space saturated by very long uptime with many peers.","solutions":["Investigate and fix hostinfo/index leaks — ensure DeleteHostInfo is called when connections close","Restart or recycle the process to clear a saturated index map","Reduce handshake churn (fix flapping peers, aggressive reconnect timers) that fills the index space"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if len(hm.indexes) >= maxIndexes-1 {\n    return fmt.Errorf(\"index map nearly exhausted\")\n}","typeGuard":null,"tryCatchPattern":"index, err := hm.allocateIndex(hh)\nif err != nil {\n    // cannot allocate: shed load / fail handshake; retry with backoff\n    return err\n}","preventionTips":["Audit for hostinfo leaks and always call DeleteHostInfo on close","Cap concurrent pending handshakes","Restart/recycle long-running processes with heavy churn"],"tags":["handshake","resource-exhaustion","index-allocation"],"backgroundTag":"resource-exhaustion","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"}