{"record":{"id":"d7bc084003b27990","repo":"AdguardTeam/AdGuardHome","slug":"subnet-s-does-not-contain-the-ip-q","errorCode":null,"errorMessage":"subnet %s does not contain the ip %q","messagePattern":"subnet (.+?) does not contain the ip %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/dhcpd/v4_unix.go","lineNumber":326,"sourceCode":"\t\tif !isStatic && l.Hostname == lease.Hostname {\n\t\t\tl.Hostname = \"\"\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// addLease adds a dynamic or static lease.\nfunc (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","sourceCodeStart":308,"sourceCodeEnd":344,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/dhcpd/v4_unix.go#L308-L344","documentation":"addLease rejects a static lease whose IP is not inside the configured DHCP subnet. Static leases must belong to the served subnet, otherwise the server cannot legitimately hand them out. The subnet in the message is the server's configured range.","triggerScenarios":"Calling ResetLeases/UpdateStaticLease/AddStaticLease (via addLease) with l.IsStatic=true and an l.IP outside s.conf.subnet — e.g. a static lease configured for a different subnet than the DHCP interface's subnet.","commonSituations":"Changed the DHCP interface or its subnet but kept old static lease entries; copied static lease configs between networks; typo in the static lease IP (wrong octet or wrong subnet prefix).","solutions":["Correct the static lease IP so it lies within the configured DHCP subnet","Update the DHCP subnet configuration to cover the static lease range","Remove stale static leases after changing network topology"],"exampleFix":"// before\nsubnet: 192.168.1.0/24\nstatic_lease: { ip: 10.0.0.50, mac: \"aa:bb:cc:dd:ee:ff\" }\n\n// after\nstatic_lease: { ip: 192.168.1.50, mac: \"aa:bb:cc:dd:ee:ff\" }","handlingStrategy":"validation","validationCode":"// before AddStaticLease / ResetLeases\nif !subnet.Contains(lease.IP) {\n    return fmt.Errorf(\"lease %s outside subnet %s\", lease.IP, subnet)\n}","typeGuard":null,"tryCatchPattern":"if err := srv.AddStaticLease(l); err != nil {\n    if strings.Contains(err.Error(), \"does not contain the ip\") {\n        // fix lease IP to be within subnet\n    }\n}","preventionTips":["Validate static lease IPs against the configured subnet at config load time","Re-audit static leases whenever the DHCP subnet changes","Automate config linting for lease/subnet mismatches"],"tags":["dhcp","static-lease","subnet","validation","ipv4"],"backgroundTag":"ip-not-in-subnet","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}