{"record":{"id":"ffc615d354df8915","repo":"juanfont/headscale","slug":"allocating-ipv6-address-w","errorCode":null,"errorMessage":"allocating IPv6 address: %w","messagePattern":"allocating IPv6 address: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"hscontrol/db/ip.go","lineNumber":157,"sourceCode":"\nfunc (i *IPAllocator) Next() (*netip.Addr, *netip.Addr, error) {\n\tvar (\n\t\terr  error\n\t\tret4 *netip.Addr\n\t\tret6 *netip.Addr\n\t)\n\n\tif i.prefix4 != nil {\n\t\tret4, err = i.allocateNext(&i.prev4, i.prefix4)\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"allocating IPv4 address: %w\", err)\n\t\t}\n\t}\n\n\tif i.prefix6 != nil {\n\t\tret6, err = i.allocateNext(&i.prev6, i.prefix6)\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"allocating IPv6 address: %w\", err)\n\t\t}\n\t}\n\n\treturn ret4, ret6, nil\n}\n\nvar ErrCouldNotAllocateIP = errors.New(\"failed to allocate IP\")\n\n// allocateNext allocates the next address from prefix under i.mu, advancing\n// prev so a run of allocations (e.g. BackfillNodeIPs) does not rescan\n// already-issued addresses, and so prev is read under the lock rather than in\n// the caller's frame.\nfunc (i *IPAllocator) allocateNext(prev *netip.Addr, prefix *netip.Prefix) (*netip.Addr, error) {\n\ti.mu.Lock()\n\tdefer i.mu.Unlock()\n\n\tret, err := i.next(*prev, prefix)\n\tif err != nil {","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/hscontrol/db/ip.go#L139-L175","documentation":"Same as 415 for the IPv6 family: Next() could not allocate a v6 address from the configured v6 prefix. Includes the random-strategy failure path (randomNext error) in addition to exhaustion.","triggerScenarios":"v6 prefix exhausted (only realistic with a deliberately tiny prefix), or the random strategy failing to produce a usable start address (chained error from randomNext — see 417/418).","commonSituations":"Custom narrow fd7a::/120-style prefixes; removing the default v6 prefix while nodes still request dual-stack.","solutions":["Widen or restore the IPv6 prefix (default fd7a:115c:a1e0::/48).","Inspect the chained error: if it comes from the random strategy, switch allocation strategy to sequential (ip_allocation_strategy) to bypass.","Prune expired/deleted nodes to reclaim addresses."],"exampleFix":"# before\nip_prefixes:\n  - 100.64.0.0/10\n  - fd7a:115c:a1e0::/126 # 4 addresses, exhausted\n\n# after\nip_prefixes:\n  - 100.64.0.0/10\n  - fd7a:115c:a1e0::/48","handlingStrategy":"fallback","validationCode":"// Mirror of the v4 check applied to the v6 prefix:\n// ensure fd7a:115c:a1e0::/48 (or wider) and nodeCount well below 2^80.","typeGuard":null,"tryCatchPattern":"// Fall back to v4-only or sequential strategy while the v6 prefix is\n// enlarged; retry registration after config reload.","preventionTips":["Keep the default /48 v6 prefix unless there is a strong reason.","If random strategy errors repeat, switch to sequential."],"tags":["ip-allocation","ipv6","capacity","config"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}