{"record":{"id":"41f5017224c3985e","repo":"AdguardTeam/AdGuardHome","slug":"dnscrypt-config-file-w","errorCode":null,"errorMessage":"dnscrypt_config_file: %w","messagePattern":"dnscrypt_config_file: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/home/dns.go","lineNumber":375,"sourceCode":"\tif extTLSConf.PortDNSOverQUIC != 0 {\n\t\tdnsConf.QUICListenAddrs = ipsToUDPAddrs(addrs, extTLSConf.PortDNSOverQUIC)\n\t}\n\n\treturn dnsConf, nil\n}\n\n// newDNSCryptConfig converts values from the configuration file into the\n// internal DNSCrypt settings for the DNS server.  extTLSConf must not be nil.\nfunc newDNSCryptConfig(\n\textTLSConf *aghtls.ExtendedTLSConfig,\n\taddrs []netip.Addr,\n) (dnsCryptConf *dnsforward.DNSCryptConfig, err error) {\n\tif extTLSConf.PortDNSCrypt == 0 {\n\t\treturn nil, nil\n\t}\n\n\tif extTLSConf.DNSCryptConfigFile == \"\" {\n\t\treturn nil, fmt.Errorf(\"dnscrypt_config_file: %w\", errors.ErrEmptyValue)\n\t}\n\n\tf, err := os.Open(extTLSConf.DNSCryptConfigFile)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"opening dnscrypt config: %w\", err)\n\t}\n\tdefer func() { err = errors.WithDeferred(err, f.Close()) }()\n\n\trc := &dnscrypt.ResolverConfig{}\n\terr = yaml.NewDecoder(f).Decode(rc)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"decoding dnscrypt config: %w\", err)\n\t}\n\n\tcert, err := rc.NewCert()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"creating dnscrypt cert: %w\", err)\n\t}","sourceCodeStart":357,"sourceCodeEnd":393,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/home/dns.go#L357-L393","documentation":"DNSCrypt is enabled (PortDNSCrypt is non-zero) but no DNSCryptConfigFile was supplied, so the resolver certificate cannot be loaded. The code explicitly returns errors.ErrEmptyValue wrapped with 'dnscrypt_config_file'.","triggerScenarios":"Setting the dnscrypt listening port in the TLS/DNS config while leaving the dnscrypt_config_file path empty — newDNSCryptConfig short-circuits with ErrEmptyValue.","commonSituations":"Hand-editing config.yaml to add a DNSCrypt port without adding the config file path, or a setup wizard/migration dropping the field.","solutions":["Set dnscrypt_config_file in the tls config section to a valid path, or","Remove/clear the dnscrypt port (set to 0) if DNSCrypt is not wanted","If enabling DNSCrypt, generate a config with dnscrypt generate-cert or copy the sample and reference it"],"exampleFix":"# before\ntls:\n  port_dnscrypt: 5443\n  # dnscrypt_config_file missing\n# after\ntls:\n  port_dnscrypt: 5443\n  dnscrypt_config_file: /opt/AdGuardHome/dnscrypt-config.yaml","handlingStrategy":"validation","validationCode":"// before enabling DNSCrypt\nif tlsConf.PortDNSCrypt != 0 && tlsConf.DNSCryptConfigFile == \"\" {\n    return fmt.Errorf(\"dnscrypt port set but dnscrypt_config_file is empty\")\n}","typeGuard":"func dnscryptConfigComplete(t *TLSConfig) bool {\n    return t.PortDNSCrypt == 0 || t.DNSCryptConfigFile != \"\"\n}","tryCatchPattern":"if err != nil { // from newDNSCryptConfig\n    if errors.Is(err, errors.ErrEmptyValue) {\n        // set dnscrypt_config_file or clear port_dnscrypt, then retry init\n    }\n}","preventionTips":["Treat port_dnscrypt and dnscrypt_config_file as a pair in config templates","Add schema validation rejecting a dnscrypt port without a config path","Prefer the UI/setup wizard which enforces the pairing"],"tags":["dns","adguard-home","dnscrypt","missing-config","configuration"],"backgroundTag":"missing-config-value","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}