AdguardTeam/AdGuardHome · error

dhcpv4 or dhcpv6 configuration must be complete

Error message

dhcpv4 or dhcpv6 configuration must be complete

What it means

Returned by createServers when the config has Enabled set to true (aghalg.NBTrue) but neither the DHCPv4 nor the DHCPv6 sub-configuration turned out to be complete/enabled. It prevents starting a DHCP 'server' that would actually serve nothing on either protocol.

Source

Thrown at internal/dhcpd/http_unix.go:310

	return srv6, enabled, err
}

// createServers returns DHCPv4 and DHCPv6 servers created from the provided
// configuration conf.
func (s *server) createServers(conf *dhcpServerConfigJSON) (srv4, srv6 DHCPServer, err error) {
	srv4, v4Enabled, err := s.handleDHCPSetConfigV4(conf)
	if err != nil {
		return nil, nil, fmt.Errorf("bad dhcpv4 configuration: %w", err)
	}

	srv6, v6Enabled, err := s.handleDHCPSetConfigV6(conf)
	if err != nil {
		return nil, nil, fmt.Errorf("bad dhcpv6 configuration: %w", err)
	}

	if conf.Enabled == aghalg.NBTrue && !v4Enabled && !v6Enabled {
		return nil, nil, fmt.Errorf("dhcpv4 or dhcpv6 configuration must be complete")
	}

	return srv4, srv6, nil
}

// handleDHCPSetConfig is the handler for the POST /control/dhcp/set_config
// HTTP API.
func (s *server) handleDHCPSetConfig(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	l := s.conf.Logger

	conf := &dhcpServerConfigJSON{}
	conf.Enabled = aghalg.BoolToNullBool(s.conf.Enabled)
	conf.InterfaceName = s.conf.InterfaceName

	err := json.NewDecoder(r.Body).Decode(conf)
	if err != nil {
		aghhttp.ErrorAndLog(

View on GitHub (pinned to b41aefbe51)

Solutions

  1. Fully specify at least one protocol block (v4 or v6): interface, range start/end, gateway/subnet as required
  2. Check the per-protocol enabled flags inside v4/v6 blocks are not false while expecting the server to serve them
  3. Re-read the config with GET /control/dhcp/config to see which block is incomplete, then fix and re-POST

Example fix

// before
{"enabled":true,"v4":{},"v6":{}}
// -> 400 dhcpv4 or dhcpv6 configuration must be complete

// after
{"enabled":true,"v4":{"enabled":true,"interface_name":"eth0","range_start":"192.168.1.50","range_end":"192.168.1.100","subnet_mask":"255.255.255.0","gateway_ip":"192.168.1.1"},"v6":{}}
Defensive patterns

Strategy: validation

Validate before calling

func configComplete(c Config) bool {
	return c.V4.enabledAndFilled() || c.V6.enabledAndFilled()
	// i.e. at least one block has interface + valid range + required IPs
}

Prevention

When it happens

Trigger: POSTing {"enabled": true} with both v4 and v6 blocks disabled, empty, or lacking the required fields (e.g. no range set), so v4Enabled and v6Enabled both come back false.

Common situations: Flipping the master Enabled toggle in the UI before filling in either protocol's settings; disabling v4 while forgetting to complete the v6 block; partial configs left over from migrations.

Related errors


AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27). Data as JSON: /api/errors/3f8652f9cf341c41. Report an issue: GitHub.