{"record":{"id":"fa54e9e3f2cc686b","repo":"AdguardTeam/AdGuardHome","slug":"decoding-dnscrypt-config-w","errorCode":null,"errorMessage":"decoding dnscrypt config: %w","messagePattern":"decoding dnscrypt config: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/home/dns.go","lineNumber":387,"sourceCode":") (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}\n\n\treturn &dnsforward.DNSCryptConfig{\n\t\tResolverCert:   cert,\n\t\tUDPListenAddrs: ipsToUDPAddrs(addrs, extTLSConf.PortDNSCrypt),\n\t\tTCPListenAddrs: ipsToTCPAddrs(addrs, extTLSConf.PortDNSCrypt),\n\t\tProviderName:   rc.ProviderName,\n\t}, nil\n}\n\n// dnsEncryption contains different types of TLS encryption addresses.\ntype dnsEncryption struct {\n\thttps string","sourceCodeStart":369,"sourceCodeEnd":405,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/home/dns.go#L369-L405","documentation":"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).","triggerScenarios":"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.","commonSituations":"Hand-editing the dnscrypt config, converting formats with a broken script, or truncation during file transfer leaving invalid YAML.","solutions":["Run the file through a YAML linter or 'yamllint' to find the syntax error","Compare against a known-good dnscrypt ResolverConfig: required fields include provider_name, public_key, private_key, cert_secret, cert_file_type","Regenerate the config with dnscrypt generate-cert if hand-fixing fails","Check for tabs vs spaces and BOM/trailing garbage from copy-paste"],"exampleFix":"# before (invalid: tab indentation, missing keys)\nresolver:\n\tname: myresolver\n# after\nprovider_name: 2.dnscrypt-cert.example.com\npublic_key: <hex>\nprivate_key: <hex>\ncert_secret: <hex>\ncert_file_type: 1","handlingStrategy":"validation","validationCode":"// parse-check before startup\nimport \"gopkg.in/yaml.v3\"\nfunc yamlParses(path string, into any) error {\n    b, err := os.ReadFile(path); if err != nil { return err }\n    return yaml.Unmarshal(b, into)\n}\nif err := yamlParses(tlsConf.DNSCryptConfigFile, &dnscrypt.ResolverConfig{}); err != nil {\n    return fmt.Errorf(\"dnscrypt yaml invalid: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n    var yte *yaml.TypeError\n    if errors.As(err, &yte) {\n        for _, l := range yte.Errors { log.Error(\"yaml field error\", \"detail\", l) }\n    }\n    return fmt.Errorf(\"decoding dnscrypt config: %w\", err)\n}","preventionTips":["Lint dnscrypt YAML in CI (yamllint, no tabs)","Generate dnscrypt configs with tooling instead of hand-editing","Keep a known-good copy to diff against when errors appear"],"tags":["dns","adguard-home","dnscrypt","yaml","parsing"],"backgroundTag":"yaml-parse-error","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}