{"record":{"id":"7617ca5220a71357","repo":"AdguardTeam/AdGuardHome","slug":"hostname-w","errorCode":null,"errorMessage":"hostname: %w","messagePattern":"hostname: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/dhcpd/v4_unix.go","lineNumber":335,"sourceCode":"func (s *v4Server) addLease(l *dhcpsvc.Lease) (err error) {\n\tr := s.conf.ipRange\n\tleaseIP := net.IP(l.IP.AsSlice())\n\toffset, inOffset := r.offset(leaseIP)\n\n\tif l.IsStatic {\n\t\t// TODO(a.garipov, d.seregin): Subnet can be nil when dhcp server is\n\t\t// disabled.\n\t\tif sn := s.conf.subnet; !sn.Contains(l.IP) {\n\t\t\treturn fmt.Errorf(\"subnet %s does not contain the ip %q\", sn, l.IP)\n\t\t}\n\t} else if !inOffset {\n\t\treturn fmt.Errorf(\"lease %s (%s) out of range, not adding\", l.IP, l.HWAddr)\n\t}\n\n\t// TODO(e.burkov):  l must have a valid hostname here, investigate.\n\tif l.Hostname != \"\" {\n\t\tif _, ok := s.hostsIndex[l.Hostname]; ok {\n\t\t\treturn fmt.Errorf(\"hostname: %w\", errors.ErrDuplicated)\n\t\t}\n\n\t\ts.hostsIndex[l.Hostname] = l\n\t}\n\ts.ipIndex[l.IP] = l\n\n\ts.leases = append(s.leases, l)\n\ts.leasedOffsets.set(offset, true)\n\n\treturn nil\n}\n\n// rmLease removes a lease with the same properties.\nfunc (s *v4Server) rmLease(lease *dhcpsvc.Lease) (err error) {\n\tif len(s.leases) == 0 {\n\t\treturn nil\n\t}\n","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/dhcpd/v4_unix.go#L317-L353","documentation":"addLease found that another lease already owns the requested hostname in hostsIndex, so it returns the hostname wrapped around errors.ErrDuplicated. The DHCP server enforces unique hostnames across leases so DNS/RDNS entries stay unambiguous.","triggerScenarios":"Adding or resetting a lease whose Hostname already exists in s.hostsIndex under a different MAC/IP — e.g. two devices both claiming hostname \"android-abc123\", or re-adding a lease set containing a duplicate hostname.","commonSituations":"Cloned VMs/IoT devices with identical default hostnames; importing a lease file with duplicates; replacing a device while its old lease still holds the hostname.","solutions":["Rename one of the conflicting clients' hostnames","Remove or expire the stale lease holding the hostname (or reset leases)","When resetting leases in bulk, deduplicate hostnames before insertion"],"exampleFix":"// before\n{ hostname: \"printer\", mac: \"aa:..\" }\n{ hostname: \"printer\", mac: \"bb:..\" }\n\n// after\n{ hostname: \"printer\", mac: \"aa:..\" }\n{ hostname: \"printer-2\", mac: \"bb:..\" }","handlingStrategy":"validation","validationCode":"// dedupe hostnames before bulk add/reset\nseen := map[string]bool{}\nfor _, l := range leases {\n    if l.Hostname != \"\" && seen[l.Hostname] { l.Hostname = \"\" }\n    seen[l.Hostname] = true\n}","typeGuard":null,"tryCatchPattern":"if err := srv.addLease(l); errors.Is(err, errors.ErrDuplicated) {\n    // rename or clear the hostname and retry\n}","preventionTips":["Deduplicate hostnames when merging lease sets","Rename cloned devices to unique names","Clear hostnames on conflicting imports rather than failing"],"tags":["dhcp","hostname","duplicate","conflict","lease"],"backgroundTag":"duplicate-hostname-conflict","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}