kubernetes/kops · error

couldn't open DNS provider configuration %s: %#v

Error message

couldn't open DNS provider configuration %s: %#v

What it means

dnsprovider.InitDnsProvider returns "couldn't open DNS provider configuration %s: %#v" when os.Open(configFilePath) fails, i.e. the configuration file passed for the DNS provider does not exist or is unreadable. This happens before any provider plugin is invoked, so the provider is never constructed. The %#v prints the underlying *os.PathError (path, op, errno).

Source

Thrown at dnsprovider/pkg/dnsprovider/plugins.go:90

	}
	return registeredProviders
}

// InitDnsProvider creates an instance of the named DNS provider.
func InitDnsProvider(name string, configFilePath string) (Interface, error) {
	var dns Interface
	var err error

	if name == "" {
		klog.Info("No DNS provider specified.")
		return nil, nil
	}

	if configFilePath != "" {
		var config *os.File
		config, err = os.Open(configFilePath)
		if err != nil {
			return nil, fmt.Errorf("couldn't open DNS provider configuration %s: %#v", configFilePath, err)
		}

		defer config.Close()
		dns, err = GetDnsProvider(name, config)
	} else {
		// Pass explicit nil so plugins can actually check for nil. See
		// "Why is my nil error value not equal to nil?" in golang.org/doc/faq.
		dns, err = GetDnsProvider(name, nil)
	}

	if err != nil {
		return nil, fmt.Errorf("could not init DNS provider %q: %v", name, err)
	}
	if dns == nil {
		return nil, fmt.Errorf("unknown DNS provider %q", name)
	}

	return dns, nil

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check the path in the error message: confirm the file exists (ls -l <path>) and is readable by the controller process/user.
  2. Correct the --config-file flag or create the configuration file at that exact path.
  3. Verify the ConfigMap/volume mount exists inside the pod if running in-cluster.
  4. If no config is actually needed, pass an empty configFilePath so the code takes the GetDnsProvider(name, nil) branch.

Example fix

// before: file missing
provider, err := dnsprovider.InitDnsProvider("aws-route53", "/etc/dns/config.yaml")
// after: ensure file exists or pass empty path
defConfig := ""
provider, err := dnsprovider.InitDnsProvider("aws-route53", defConfig)
Defensive patterns

Strategy: validation

Validate before calling

// Go: verify the config file before calling InitDnsProvider
if configFilePath != "" {
    if fi, err := os.Stat(configFilePath); err != nil || fi.IsDir() {
        return fmt.Errorf("DNS provider config %q missing or is a directory", configFilePath)
    }
}

Try / catch

provider, err := dnsprovider.InitDnsProvider(name, path)
if err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) {
        klog.Errorf("config path problem: op=%s path=%s: %v", pe.Op, pe.Path, pe.Err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling InitDnsProvider(name, configFilePath) with a non-empty configFilePath that does not exist, is a directory, or lacks read permissions. Callers like dns-controller pass the --config-file path through from CLI flags.

Common situations: Typo in the --config-file flag; file mounted/created after the controller starts; running in a container without the config volume mounted; wrong path due to working-directory differences.

Understand the failure class

Background: "Config file not found": what it means and how to fix it in docker-sync, Maven, Vagrant, Turborepo and other tools — this error's family across 60 libraries.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/0790b6f09552b3e4. Report an issue: GitHub.