kubernetes/kops · error
reading /etc/os-release: %v
Error message
reading /etc/os-release: %v
What it means
FindDistribution in util/pkg/distributions identifies the host OS by parsing /etc/os-release. When the file does not exist or cannot be read (the read errored and the file is not valid), the function returns Distribution{} with this error wrapping the underlying OS error. It means the code could not even gather the OS facts needed to identify the distro, before any distro-matching happens.
Source
Thrown at util/pkg/distributions/identify.go:44
)
// FindDistribution identifies the distribution on which we are running
func FindDistribution(rootfs string) (Distribution, error) {
// All supported distros have an /etc/os-release file
osReleaseBytes, err := os.ReadFile(path.Join(rootfs, "etc/os-release"))
osRelease := make(map[string]string)
if err == nil {
for _, line := range strings.Split(string(osReleaseBytes), "\n") {
line = strings.TrimSpace(line)
if strings.HasPrefix(line, "ID=") {
osRelease["ID"] = strings.Trim(line[3:], "\"")
}
if strings.HasPrefix(line, "VERSION_ID=") {
osRelease["VERSION_ID"] = strings.Trim(line[11:], "\"")
}
}
} else {
return Distribution{}, fmt.Errorf("reading /etc/os-release: %v", err)
}
distro := fmt.Sprintf("%s-%s", osRelease["ID"], osRelease["VERSION_ID"])
// Most distros have a fixed VERSION_ID
switch distro {
case "amzn-2023":
return DistributionAmazonLinux2023, nil
case "amzn-2027":
return DistributionAmazonLinux2027, nil
case "debian-11":
return DistributionDebian11, nil
case "debian-12":
return DistributionDebian12, nil
case "debian-13":
return DistributionDebian13, nil
case "fedora-41":
return DistributionFedora41, nilView on GitHub (pinned to 4c8573c808)
Solutions
- Ensure the target system (or rootfs) actually contains /etc/os-release; check with `ls -l /etc/os-release`
- If a rootfs argument is used, correct it to the real root (e.g. "/" or the mounted node root)
- Use a standard base image (debian/ubuntu/rocky/flatcar/amazon-linux) that ships os-release data
- Inspect the wrapped error (%v) — ENOENT means the file is absent, EACCES means permissions
Example fix
// before // building a scratch container image for nodes, no /etc/os-release // after FROM debian:bookworm-slim # any base that ships /etc/os-release
Defensive patterns
Strategy: validation
Validate before calling
// check the target rootfs before calling FindDistribution:
osRelease := filepath.Join(rootfs, "etc", "os-release")
if _, err := os.Stat(osRelease); err != nil {
return fmt.Errorf("cannot identify distro: %s is missing in rootfs %q", osRelease, rootfs)
} Type guard
func hasOSRelease(rootfs string) bool {
fi, err := os.Stat(filepath.Join(rootfs, "etc", "os-release"))
return err == nil && !fi.IsDir()
} Try / catch
distro, err := distributions.FindDistribution("/")
if err != nil {
return fmt.Errorf("OS identification failed: %w (is this a Linux system with /etc/os-release?)", err)
} Prevention
- Only run distro-identification code on Linux hosts or valid chroot roots
- Use standard base images that ship /etc/os-release (debian, ubuntu, alpine, etc.) — avoid scratch images
- Double-check the rootfs argument points at the actual filesystem root
- Test on macOS dev machines is a common false positive — guard with runtime.GOOS == "linux"
When it happens
Trigger: Calling FindDistribution(rootfs) where rootfs/etc/os-release is missing (non-Linux host, macOS dev machine, wrong chroot/root path passed), unreadable due to permissions, or the read returns an I/O error (broken mount, corrupted container image).
Common situations: Running kOps/nodeup inside a minimal container or stage-1 image that ships no /etc/os-release; pointing FindDistribution at the wrong rootfs directory; running unit/tooling on macOS where /etc/os-release does not exist; a stripped-down base image (e.g. scratch or distroless variant) used for nodes.
Related errors
- error creating temp dir: %v
- error writing temp file: %v
- error reading addons file %s: %v
- reading %q certificate: %v
- error reading user provided private key %q: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/de3e1b98502b345b.
Report an issue: GitHub.