AdguardTeam/AdGuardHome · error
creating dnscrypt cert: %w
Error message
creating dnscrypt cert: %w
What it means
The parsed DNSCrypt ResolverConfig was rejected by rc.NewCert(), which builds the dnscrypt.ServerCert from the provider name, keys, and secret. Failure means the cryptographic material is invalid or inconsistent — bad hex keys, secret length wrong, or an unsupported certificate file type/signature mismatch.
Source
Thrown at internal/home/dns.go:392
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
tls string
quic string
}
// getDNSEncryption returns the TLS encryption addresses that AdGuard HomeView on GitHub (pinned to b41aefbe51)
Solutions
- Regenerate the full keypair and config together: dnscrypt generate-cert --provider-name 2.dnscrypt-cert.example.com and use ALL emitted values
- Verify public_key/private_key are exactly 64 hex chars each and cert_secret is 32 hex chars
- Ensure provider_name matches the '<version>.dnscrypt-cert.<domain>' pattern
- Confirm cert_file_type matches the certificate format (0=plain, 1=rsa, 2=edge, 3=rsa8)
Example fix
# regenerate a consistent set dnscrypt generate-cert \ --provider-name 2.dnscrypt-cert.example.com \ --out dnscrypt.yaml # then point tls.dnscrypt_config_file at the new file and restart
Defensive patterns
Strategy: validation
Validate before calling
// structural pre-check of key material
import "encoding/hex"
func keysConsistent(rc dnscrypt.ResolverConfig) error {
if len(rc.PublicKey) != 64 || len(rc.PrivateKey) != 64 { return fmt.Errorf("keys must be 64 hex chars") }
if _, err := hex.DecodeString(rc.PublicKey); err != nil { return fmt.Errorf("bad public_key hex") }
if _, err := hex.DecodeString(rc.PrivateKey); err != nil { return fmt.Errorf("bad private_key hex") }
return nil
} Type guard
func validProviderName(name string) bool {
parts := strings.Split(name, ".")
return len(parts) >= 4 && parts[1] == "dnscrypt-cert"
} Try / catch
if _, err := rc.NewCert(); err != nil {
// regenerate the whole config — partial key edits never recover
log.Error("dnscrypt cert invalid; regenerate keypair", slogutil.KeyError, err)
} Prevention
- Always rotate public_key/private_key/cert_secret together via generate-cert
- Never hand-truncate or retype hex key material
- Store the generated dnscrypt config write-protected to prevent drift
When it happens
Trigger: rc.NewCert() errors when public_key/private_key are not valid 32-byte hex, cert_secret has the wrong length, provider_name is malformed (must look like 2.dnscrypt-cert.<domain>), or cert_file_type is not 0/1/2/3.
Common situations: Regenerating only one of the key pair, copying keys with typos/truncated hex, rotating keys without updating provider name, or wrong cert_file_type after changing hash algorithm.
Related errors
- dnscrypt_config_file: %w
- opening dnscrypt config: %w
- decoding dnscrypt config: %w
- init querylog: %w
- creating dns server: %w
AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27).
Data as JSON: /api/errors/34683e5900533778.
Report an issue: GitHub.