k3s-io/k3s · error
invalid endpoint URL %s for %s: %v
Error message
invalid endpoint URL %s for %s: %v
What it means
defaultHostConfig builds containerd's host configuration for each registry host from registries.yaml and first normalizes the endpoint via normalizeEndpointAddress(host, mirrorAddr). If that returns a parse error, it is wrapped as 'invalid endpoint URL <host> for <host>: <cause>' — both placeholders are the registry host key, and the wrapped cause says exactly what failed to parse.
Source
Thrown at pkg/agent/containerd/config.go:275
// This is the reverse of the DefaultHost normalization
if endpointURL.Host == "registry-1.docker.io" {
registry = "docker.io"
}
switch endpointURL.Path {
case "", "/", "/v2":
// If the path is empty, /, or /v2, use the default path.
endpointURL.Path = "/v2"
return registry, endpointURL, false, nil
}
return registry, endpointURL, true, nil
}
func defaultHostConfig(host, mirrorAddr string, config registries.RegistryConfig) (*templates.HostConfig, error) {
_, url, _, err := normalizeEndpointAddress(host, mirrorAddr)
if err != nil {
return nil, fmt.Errorf("invalid endpoint URL %s for %s: %v", host, host, err)
}
if host == "*" {
url = nil
}
return &templates.HostConfig{
Program: version.Program,
Default: &templates.RegistryEndpoint{
URL: url,
Config: config,
},
}, nil
}
func configForHost(configs map[string]registries.RegistryConfig, host string) registries.RegistryConfig {
// check for config under modified hostname. If the hostname is unmodified, or there is no config for
// the modified hostname, return the config for the default hostname.
if h, _ := docker.DefaultHost(host); h != host {
if c, ok := configs[h]; ok {View on GitHub (pinned to 6ba341e396)
Solutions
- Use fully-qualified endpoints with a scheme: https://mirror.example.com:5000
- Quote IPv6 literals correctly: "http://[2001:db8::1]:5000"
- Lint the registries.yaml before deploying and restart the agent/server after fixing
Example fix
# before (registries.yaml)
mirrors:
docker.io:
endpoint:
- "mirror.example.com:5000"
# after
mirrors:
docker.io:
endpoint:
- "https://mirror.example.com:5000" Defensive patterns
Strategy: validation
Validate before calling
for _, ep := range endpoints {
if _, err := url.Parse(strings.TrimSpace(ep)); err != nil {
return fmt.Errorf("registries.yaml endpoint %q is not a valid URL: %w", ep, err)
}
} Prevention
- Always write endpoints with an explicit scheme (https:// or http://)
- Bracket IPv6 literals in URLs: http://[2001:db8::1]:5000
- Lint registries.yaml in CI before it reaches nodes
When it happens
Trigger: A registries.yaml entry whose endpoint or mirror address cannot be parsed as a URL: malformed scheme ('http s://x'), stray characters, a broken IPv6 literal ('http://[::1'), or an empty endpoint string.
Common situations: Hand-edited /etc/rancher/k3s/registries.yaml; IPv6 mirror addresses missing brackets; URLs pasted with spaces or smart quotes; YAML values mangled by templating.
Related errors
- Initial server URL host is not defined for load balancer
- embedded registry mirror requires embedded containerd
- default runtime %s was not found
- insufficient PSK bytes
- nix-store not found in PATH: install nix (https://nixos.org/
AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15).
Data as JSON: /api/errors/3ab53b624b84222d.
Report an issue: GitHub.