AdguardTeam/AdGuardHome · error

decoding dnscrypt config: %w

Error message

decoding dnscrypt config: %w

What it means

The DNSCrypt config file was opened but could not be parsed as YAML into dnscrypt.ResolverConfig. The wrapped error from yaml.NewDecoder(f).Decode(rc) pinpoints the YAML syntax or type error (e.g. line/col of the bad node, or wrong field type).

Source

Thrown at internal/home/dns.go:387

) (dnsCryptConf *dnsforward.DNSCryptConfig, err error) {
	if extTLSConf.PortDNSCrypt == 0 {
		return nil, nil
	}

	if extTLSConf.DNSCryptConfigFile == "" {
		return nil, fmt.Errorf("dnscrypt_config_file: %w", errors.ErrEmptyValue)
	}

	f, err := os.Open(extTLSConf.DNSCryptConfigFile)
	if err != nil {
		return nil, fmt.Errorf("opening dnscrypt config: %w", err)
	}
	defer func() { err = errors.WithDeferred(err, f.Close()) }()

	rc := &dnscrypt.ResolverConfig{}
	err = yaml.NewDecoder(f).Decode(rc)
	if err != nil {
		return nil, fmt.Errorf("decoding dnscrypt config: %w", err)
	}

	cert, err := rc.NewCert()
	if err != nil {
		return nil, fmt.Errorf("creating dnscrypt cert: %w", err)
	}

	return &dnsforward.DNSCryptConfig{
		ResolverCert:   cert,
		UDPListenAddrs: ipsToUDPAddrs(addrs, extTLSConf.PortDNSCrypt),
		TCPListenAddrs: ipsToTCPAddrs(addrs, extTLSConf.PortDNSCrypt),
		ProviderName:   rc.ProviderName,
	}, nil
}

// dnsEncryption contains different types of TLS encryption addresses.
type dnsEncryption struct {
	https string

View on GitHub (pinned to b41aefbe51)

Solutions

  1. Run the file through a YAML linter or 'yamllint' to find the syntax error
  2. Compare against a known-good dnscrypt ResolverConfig: required fields include provider_name, public_key, private_key, cert_secret, cert_file_type
  3. Regenerate the config with dnscrypt generate-cert if hand-fixing fails
  4. Check for tabs vs spaces and BOM/trailing garbage from copy-paste

Example fix

# before (invalid: tab indentation, missing keys)
resolver:
	name: myresolver
# after
provider_name: 2.dnscrypt-cert.example.com
public_key: <hex>
private_key: <hex>
cert_secret: <hex>
cert_file_type: 1
Defensive patterns

Strategy: validation

Validate before calling

// parse-check before startup
import "gopkg.in/yaml.v3"
func yamlParses(path string, into any) error {
    b, err := os.ReadFile(path); if err != nil { return err }
    return yaml.Unmarshal(b, into)
}
if err := yamlParses(tlsConf.DNSCryptConfigFile, &dnscrypt.ResolverConfig{}); err != nil {
    return fmt.Errorf("dnscrypt yaml invalid: %w", err)
}

Try / catch

if err != nil {
    var yte *yaml.TypeError
    if errors.As(err, &yte) {
        for _, l := range yte.Errors { log.Error("yaml field error", "detail", l) }
    }
    return fmt.Errorf("decoding dnscrypt config: %w", err)
}

Prevention

When it happens

Trigger: Malformed YAML (tabs, bad indentation, duplicate keys), missing required fields, or fields whose values don't match the expected types for dnscrypt.ResolverConfig such as the certificate key pair (private_key/ public_key) not being valid hex strings.

Common situations: Hand-editing the dnscrypt config, converting formats with a broken script, or truncation during file transfer leaving invalid YAML.

Related errors


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