k3s-io/k3s · error
failed to read http config %s: %w
Error message
failed to read http config %s: %w
What it means
When --config points at an http:// or https:// URL, readConfigFileData fetches it with a plain http.Get. This error wraps any transport-level failure: DNS resolution, connection refused, TLS handshake error, or timeout. Note the code does not check the HTTP status code, so a 404 page is read as config content and fails later at YAML parsing.
Source
Thrown at pkg/configfilearg/parser.go:343
if str == "" {
return nil
}
return []any{str}
}
}
// readConfigFileData returns the contents of a local or remote file
func readConfigFileData(file string) ([]byte, error) {
u, err := url.Parse(file)
if err != nil {
return nil, fmt.Errorf("failed to parse config location %s: %w", file, err)
}
switch u.Scheme {
case "http", "https":
resp, err := http.Get(file)
if err != nil {
return nil, fmt.Errorf("failed to read http config %s: %w", file, err)
}
defer resp.Body.Close()
return io.ReadAll(resp.Body)
default:
return os.ReadFile(file)
}
}
View on GitHub (pinned to 6ba341e396)
Solutions
- From the same node, verify the URL: `curl -fsSL https://host/k3s.yaml` and fix whatever it reports (DNS, firewall, TLS).
- For self-signed certs, install the CA into the host trust store; this code path has no skip-verify option.
- If the endpoint is unreliable, download the file locally and pass a local path: `curl -o /etc/rancher/k3s/config.yaml ... && k3s server --config /etc/rancher/k3s/config.yaml`.
Example fix
# before ExecStart=/usr/local/bin/k3s server --config https://cfg.internal:8443/k3s.yaml # after (bootstrap copies it locally, immune to config-server outages) ExecStartPre=/usr/bin/curl -fsSL https://cfg.internal:8443/k3s.yaml -o /etc/rancher/k3s/config.yaml ExecStart=/usr/local/bin/k3s server --config /etc/rancher/k3s/config.yaml
Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight: URL must be reachable AND return 2xx (k3s itself ignores status codes):
resp, err := http.Get(cfgURL)
if err != nil || resp.StatusCode < 200 || resp.StatusCode > 299 {
log.Fatalf("config URL precheck failed: err=%v status=%v", err, resp.StatusCode)
}
resp.Body.Close() Try / catch
// When fetching the config yourself, retry transient errors, fail fast on permanent ones:
var body []byte
err := retry(5, time.Second*2, func() error {
resp, err := http.Get(cfgURL)
if err != nil {
var dnsErr *net.DNSError
if errors.As(err, &dnsErr) { return err } // retryable
return err
}
defer resp.Body.Close()
if resp.StatusCode != 200 { return fmt.Errorf("status %d", resp.StatusCode) }
body, err = io.ReadAll(resp.Body)
return err
}) Prevention
- Serve config over http(s) from a highly available endpoint, or cache it locally with ExecStartPre.
- Monitor the config server and alert before node reboots depend on it.
- Ensure CA certificates for HTTPS config endpoints are installed in the host trust store.
When it happens
Trigger: `k3s server --config https://host/k3s.yaml` where the host is unreachable, DNS fails, the TLS certificate is untrusted (no insecure-skip-verify here), or a proxy/firewall blocks the request (pkg/configfilearg/parser.go:341-344).
Common situations: Config server down in air-gapped or PXE-booted environments; self-signed certificate not in the host trust store; typo in the URL; egress firewall blocking the port.
Related errors
- hijacking not supported
- no IPv6 CIDRs found
- invalid node-external-ip: %w
- failed to determine MTU for %s interface
- unsupported proxy scheme: %s
AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15).
Data as JSON: /api/errors/04285bbff366ff09.
Report an issue: GitHub.