{"record":{"id":"9abacd012912dae7","repo":"slackhq/nebula","slug":"failed-to-generate-unique-localindexid-9abacd","errorCode":null,"errorMessage":"failed to generate unique localIndexId","messagePattern":"failed to generate unique localIndexId","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"relay_manager.go","lineNumber":267,"sourceCode":"\n\t\t\thm.Relays[index] = relayHostInfo\n\t\t\tnewRelay := Relay{\n\t\t\t\tType:       relayType,\n\t\t\t\tState:      state,\n\t\t\t\tLocalIndex: index,\n\t\t\t\tPeerAddr:   vpnIp,\n\t\t\t}\n\n\t\t\tif remoteIdx != nil {\n\t\t\t\tnewRelay.RemoteIndex = *remoteIdx\n\t\t\t}\n\t\t\trelayHostInfo.relayState.InsertRelay(vpnIp, index, &newRelay)\n\n\t\t\treturn index, nil\n\t\t}\n\t}\n\n\treturn 0, errors.New(\"failed to generate unique localIndexId\")\n}\n\n// EstablishRelay updates a Requested Relay to become an Established Relay, which can pass traffic.\nfunc (rm *relayManager) EstablishRelay(relayHostInfo *HostInfo, m *NebulaControl) (*Relay, error) {\n\trelay, ok := relayHostInfo.relayState.CompleteRelayByIdx(m.InitiatorRelayIndex, m.ResponderRelayIndex)\n\tif !ok {\n\t\tvar relayFrom, relayTo any\n\t\tif m.RelayFromAddr == nil {\n\t\t\trelayFrom = m.OldRelayFromAddr\n\t\t} else {\n\t\t\trelayFrom = m.RelayFromAddr\n\t\t}\n\t\tif m.RelayToAddr == nil {\n\t\t\trelayTo = m.OldRelayToAddr\n\t\t} else {\n\t\t\trelayTo = m.RelayToAddr\n\t\t}\n","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/relay_manager.go#L249-L285","documentation":"AddRelay generates a random localIndexId for the relay and loops retrying if it collides with an existing index in the hostmap. If it exhausts the loop without finding a unique id, it returns this error. With random 32-bit-ish ids this practically only happens when the hostmap is saturated with indexes.","triggerScenarios":"The id-generation retry loop in AddRelay never finds a free localIndexId — i.e. every candidate index generated collides with an existing hostmap/relay entry across all attempts.","commonSituations":"Host with an extremely large number of concurrent tunnels/relays exhausting the index space; a bug or entropy problem making generated indexes non-random; test harnesses pre-filling the index space.","solutions":["Reduce concurrent tunnel/relay count on the node or restart the process to clear stale hostmap indexes.","Verify the RNG used for index generation is seeded correctly (crypto/rand) if indexes repeat suspiciously.","Investigate leaked hostmap entries that are never cleaned up, which shrink the free index space."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"idx, err := rm.AddRelay(hi, vpnIp, idx, nil, RelayEstablished, false)\nif err != nil {\n    if err.Error() == \"failed to generate unique localIndexId\" {\n        return errors.New(\"hostmap index space exhausted; reduce tunnel count or restart\")\n    }\n    return err\n}","preventionTips":["Monitor concurrent hostmap/tunnel counts per node and cap them","Restart nodes whose hostmap has grown suspiciously large from leaks","Report persistent occurrences upstream — random index collisions across the whole retry loop usually indicate an RNG or leak bug"],"tags":["relay","hostmap","index-exhaustion","nebula"],"backgroundTag":"index-id-collision","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"}