{"record":{"id":"f61ad55bd71dacdf","repo":"caddyserver/caddy","slug":"ech-dns-provider-module-is-not-an-ech-dns-provider","errorCode":null,"errorMessage":"ECH DNS provider module is not an ECH DNS Provider: %v","messagePattern":"ECH DNS provider module is not an ECH DNS Provider: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddytls/ech.go","lineNumber":802,"sourceCode":"\tlogger       *zap.Logger\n}\n\n// CaddyModule returns the Caddy module information.\nfunc (ECHDNSPublisher) CaddyModule() caddy.ModuleInfo {\n\treturn caddy.ModuleInfo{\n\t\tID:  \"tls.ech.publishers.dns\",\n\t\tNew: func() caddy.Module { return new(ECHDNSPublisher) },\n\t}\n}\n\nfunc (dnsPub *ECHDNSPublisher) Provision(ctx caddy.Context) error {\n\tdnsProvMod, err := ctx.LoadModule(dnsPub, \"ProviderRaw\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"loading ECH DNS provider module: %v\", err)\n\t}\n\tprov, ok := dnsProvMod.(ECHDNSProvider)\n\tif !ok {\n\t\treturn fmt.Errorf(\"ECH DNS provider module is not an ECH DNS Provider: %v\", err)\n\t}\n\tdnsPub.provider = prov\n\tdnsPub.logger = ctx.Logger()\n\treturn nil\n}\n\n// PublisherKey returns the name of the DNS provider module.\n// We intentionally omit specific provider configuration (or a hash thereof,\n// since the config is likely sensitive, potentially containing an API key)\n// because it is unlikely that specific configuration, such as an API key,\n// is relevant to unique key use as an ECH config publisher.\nfunc (dnsPub ECHDNSPublisher) PublisherKey() string {\n\treturn string(dnsPub.provider.(caddy.Module).CaddyModule().ID)\n}\n\n// PublishECHConfigList publishes the given ECH config list (as binary) to the given DNS names.\n// If there is an error, it may be of type PublishECHConfigListErrors, detailing\n// potentially multiple errors keyed by associated innerName.","sourceCodeStart":784,"sourceCodeEnd":820,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddytls/ech.go#L784-L820","documentation":"After successfully loading the DNS provider module, ECHDNSPublisher type-asserts it to the ECHDNSProvider interface (GetRecords/SetRecords with context, i.e. libdns-style). If a module registers in the expected namespace but does not implement that interface, the assertion fails. Note a formatting quirk: the message interpolates err with %v, but err is nil at that point (the earlier LoadModule succeeded), so the message always ends with ': <nil>'. The failure itself means module-interface mismatch, effectively an internal/programming error.","triggerScenarios":"A custom or third-party module registered as the dns provider for ECH publishing that implements a different RecordGetter/RecordSetter shape than libdns expects; only possible with custom builds — the bundled providers all implement the interface.","commonSituations":"Custom xcaddy builds pulling an incompatible libdns provider version (major API change in libdns.ZoneRecorder interfaces across versions).","solutions":["Use the standard/bundled DNS provider modules, which are interface-guarded at compile time.","For custom builds, align the libdns version so the provider implements the same GetRecords(context.Context, string)/SetRecords signatures Caddy compiles against.","Rebuild with xcaddy so all modules compile against one libdns version."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Compile-time guard (works for custom builds): ensure your provider satisfies the interface.\nvar _ caddytls.ECHDNSProvider = (*mylibdns.Provider)(nil)","tryCatchPattern":null,"preventionTips":["Prefer bundled DNS providers; they are compile-time checked.","Keep libdns versions aligned across all modules in xcaddy builds.","Add interface guards in custom provider packages so mismatches fail at build time, not runtime."],"tags":["tls","ech","dns","module-system","type-assertion"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}