AdguardTeam/AdGuardHome · error
starting dhcp server: %w
Error message
starting dhcp server: %w
What it means
Raised when the DHCP server (v4 and/or v6) fails to start after a new configuration is applied via POST /control/dhcp/set_config. The wrapped error comes from the underlying DHCP server's Start method and typically indicates a socket-binding or interface problem (e.g. UDP port 67/68 or DHCPv6 ports already in use, missing CAP_NET_RAW/CAP_NET_ADMIN privileges, or a nonexistent interface).
Source
Thrown at internal/dhcpd/http_unix.go:220
} else {
err = fmt.Errorf("checking static ip: %w", err)
return http.StatusInternalServerError, err
}
}
if !hasStaticIP {
err = aghnet.IfaceSetStaticIP(ctx, s.conf.Logger, cmdCons, ifaceName)
if err != nil {
err = fmt.Errorf("setting static ip: %w", err)
return http.StatusInternalServerError, err
}
}
err = s.Start(ctx)
if err != nil {
return http.StatusBadRequest, fmt.Errorf("starting dhcp server: %w", err)
}
return 0, nil
}
type dhcpServerConfigJSON struct {
V4 *v4ServerConfJSON `json:"v4"`
V6 *v6ServerConfJSON `json:"v6"`
InterfaceName string `json:"interface_name"`
Enabled aghalg.NullBool `json:"enabled"`
}
func (s *server) handleDHCPSetConfigV4(
conf *dhcpServerConfigJSON,
) (srv DHCPServer, enabled bool, err error) {
if conf.V4 == nil {
return nil, false, nil
}View on GitHub (pinned to b41aefbe51)
Solutions
- Check what holds the DHCP ports: ss -lunp | grep -E ':67|:68' (or :547 for DHCPv6) and stop the conflicting daemon (e.g. systemctl stop dnsmasq)
- Ensure the binary has privileges: run as root/CAP_NET_ADMIN+CAP_NET_RAW, or set capabilities with setcap 'cap_net_raw,cap_net_admin=eip'
- Verify the configured interface name exists (ip link) and fix InterfaceName in the config
- If a previous AdGuard instance died uncleanly, make sure no orphaned process still holds the socket before retrying
Example fix
// before
sudo dnsmasq --no-daemon # still running elsewhere
curl -X POST http://127.0.0.1:3000/control/dhcp/set_config -d '{"enabled":true,...}'
// -> 400 starting dhcp server: listen udp :67: bind: address already in use
// after
sudo systemctl stop dnsmasq
curl -X POST http://127.0.0.1:3000/control/dhcp/set_config -d '{"enabled":true,...}'
// -> 200 Defensive patterns
Strategy: validation
Validate before calling
// before enabling, check ports and interface
func dhcpPrereqsOK(iface string) bool {
if _, err := net.InterfaceByName(iface); err != nil { return false }
for _, p := range []int{67, 68} {
c, err := net.ListenPacket("udp", fmt.Sprintf(":%d", p))
if err != nil { return false }
c.Close()
}
return true
} Try / catch
err := srv.Start(ctx)
if err != nil {
if strings.Contains(err.Error(), "address already in use") { /* stop conflicting daemon, retry */ }
if strings.Contains(err.Error(), "permission denied") { /* re-run with CAP_NET_RAW */ }
} Prevention
- Stop dnsmasq/isc-dhcp or any other DHCP daemon before enabling AdGuard's
- Run the binary with CAP_NET_RAW/CAP_NET_ADMIN or as root
- Verify interface names exist before saving the config
When it happens
Trigger: Calling the set_config HTTP endpoint with Enabled=true where s.Start(ctx) fails: another DHCP daemon (dnsmasq, systemd-networkd, an earlier AdGuard instance) holds UDP 67/68, the binary lacks raw-socket capabilities, or the configured interface name does not exist on the host.
Common situations: Running AdGuard Home alongside an existing DHCP server; running in a container without NET_ADMIN/NET_RAW capabilities; renaming or removing network interfaces after a config was saved; stale socket from a previous crashed instance.
Related errors
- bad dhcpv4 configuration: %w
- dhcpv4 or dhcpv6 configuration must be complete
- checking static ip: %w
- setting static ip: %w
- bad dhcpv6 configuration: %w
AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27).
Data as JSON: /api/errors/bfb4cc5598fd297f.
Report an issue: GitHub.