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, nil

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Ensure the target system (or rootfs) actually contains /etc/os-release; check with `ls -l /etc/os-release`
  2. If a rootfs argument is used, correct it to the real root (e.g. "/" or the mounted node root)
  3. Use a standard base image (debian/ubuntu/rocky/flatcar/amazon-linux) that ships os-release data
  4. 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

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


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