{"record":{"id":"e9a169f88142ffdb","repo":"AdguardTeam/AdGuardHome","slug":"v-is-not-an-ipv4-s","errorCode":null,"errorMessage":"%v is not an IPv4 %s","messagePattern":"(.+?) is not an IPv4 (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/dhcpd/config.go","lineNumber":162,"sourceCode":"\n\t// notify is a way to signal to other components that leases have been\n\t// changed.  notify must be called outside of locked sections, since the\n\t// clients might want to get the new data.\n\t//\n\t// TODO(a.garipov): This is utter madness and must be refactored.  It just\n\t// begs for deadlock bugs and other nastiness.\n\tnotify func(uint32)\n}\n\n// errNilConfig is an error returned by validation method if the config is nil.\nconst errNilConfig errors.Error = \"nil config\"\n\n// ensureV4 returns an unmapped version of ip.  An error is returned if the\n// passed ip is not an IPv4.\nfunc ensureV4(ip netip.Addr, kind string) (ip4 netip.Addr, err error) {\n\tip4 = ip.Unmap()\n\tif !ip4.IsValid() || !ip4.Is4() {\n\t\treturn netip.Addr{}, fmt.Errorf(\"%v is not an IPv4 %s\", ip, kind)\n\t}\n\n\treturn ip4, nil\n}\n\n// Validate returns an error if c is not a valid configuration.\n//\n// TODO(e.burkov):  Don't set the config fields when the server itself will stop\n// containing the config.\nfunc (c *V4ServerConf) Validate() (err error) {\n\tdefer func() { err = errors.Annotate(err, \"dhcpv4: %w\") }()\n\n\tif c == nil {\n\t\treturn errNilConfig\n\t}\n\n\tgatewayIP, err := ensureV4(c.GatewayIP, \"address\")\n\tif err != nil {","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/dhcpd/config.go#L144-L180","documentation":"ensureV4 verifies that an address used in DHCPv4 configuration is a valid IPv4 address. The address is either invalid (zero), IPv6, or an IPv4-in-IPv6 mapped address that unmapped to something non-IPv4. 'kind' names the field (e.g. gateway, range start).","triggerScenarios":"Calling Validate on DHCPv4 config where RangeStart, RangeEnd, or gateway is an IPv6 address or an unparseable/zero netip.Addr (e.g. a typo like 192.168.1.256 or an address left unset as netip.Addr{}).","commonSituations":"UI or API input of an IPv6 address into an IPv4 field, forgetting to set the gateway, or parsing failures upstream that yield invalid Addr values.","solutions":["Correct the offending field to a valid dotted-quad IPv4 address","Ensure RangeStart/RangeEnd/gateway are set (not empty) before enabling DHCPv4","If addresses come from parsing, check parse errors before Validate"],"exampleFix":"// before\ncfg.GatewayIP = netip.MustParseAddr(\"fe80::1\")\n// after\ncfg.GatewayIP = netip.MustParseAddr(\"192.168.1.1\")","handlingStrategy":"validation","validationCode":"// before Validate/Create\nfor _, ip := range []netip.Addr{cfg.RangeStart, cfg.RangeEnd, gatewayIP} {\n    if !ip.IsValid() || !ip.Is4() { return errors.New(\"need valid IPv4\") }\n}","typeGuard":"func isIPv4(a netip.Addr) bool { a = a.Unmap(); return a.IsValid() && a.Is4() }","tryCatchPattern":null,"preventionTips":["Validate user-supplied addresses at the API/UI boundary","Parse with netip.ParseAddr and handle errors before use"],"tags":["dhcp","ipv4","validation","config"],"backgroundTag":"invalid-ip-address","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}