{"record":{"id":"de3e1b98502b345b","repo":"kubernetes/kops","slug":"reading-etc-os-release-v","errorCode":null,"errorMessage":"reading /etc/os-release: %v","messagePattern":"reading /etc/os-release: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/pkg/distributions/identify.go","lineNumber":44,"sourceCode":")\n\n// FindDistribution identifies the distribution on which we are running\nfunc FindDistribution(rootfs string) (Distribution, error) {\n\t// All supported distros have an /etc/os-release file\n\tosReleaseBytes, err := os.ReadFile(path.Join(rootfs, \"etc/os-release\"))\n\tosRelease := make(map[string]string)\n\tif err == nil {\n\t\tfor _, line := range strings.Split(string(osReleaseBytes), \"\\n\") {\n\t\t\tline = strings.TrimSpace(line)\n\t\t\tif strings.HasPrefix(line, \"ID=\") {\n\t\t\t\tosRelease[\"ID\"] = strings.Trim(line[3:], \"\\\"\")\n\t\t\t}\n\t\t\tif strings.HasPrefix(line, \"VERSION_ID=\") {\n\t\t\t\tosRelease[\"VERSION_ID\"] = strings.Trim(line[11:], \"\\\"\")\n\t\t\t}\n\t\t}\n\t} else {\n\t\treturn Distribution{}, fmt.Errorf(\"reading /etc/os-release: %v\", err)\n\t}\n\n\tdistro := fmt.Sprintf(\"%s-%s\", osRelease[\"ID\"], osRelease[\"VERSION_ID\"])\n\n\t// Most distros have a fixed VERSION_ID\n\tswitch distro {\n\tcase \"amzn-2023\":\n\t\treturn DistributionAmazonLinux2023, nil\n\tcase \"amzn-2027\":\n\t\treturn DistributionAmazonLinux2027, nil\n\tcase \"debian-11\":\n\t\treturn DistributionDebian11, nil\n\tcase \"debian-12\":\n\t\treturn DistributionDebian12, nil\n\tcase \"debian-13\":\n\t\treturn DistributionDebian13, nil\n\tcase \"fedora-41\":\n\t\treturn DistributionFedora41, nil","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/util/pkg/distributions/identify.go#L26-L62","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\n// building a scratch container image for nodes, no /etc/os-release\n// after\nFROM debian:bookworm-slim  # any base that ships /etc/os-release","handlingStrategy":"validation","validationCode":"// check the target rootfs before calling FindDistribution:\nosRelease := filepath.Join(rootfs, \"etc\", \"os-release\")\nif _, err := os.Stat(osRelease); err != nil {\n    return fmt.Errorf(\"cannot identify distro: %s is missing in rootfs %q\", osRelease, rootfs)\n}","typeGuard":"func hasOSRelease(rootfs string) bool {\n    fi, err := os.Stat(filepath.Join(rootfs, \"etc\", \"os-release\"))\n    return err == nil && !fi.IsDir()\n}","tryCatchPattern":"distro, err := distributions.FindDistribution(\"/\")\nif err != nil {\n    return fmt.Errorf(\"OS identification failed: %w (is this a Linux system with /etc/os-release?)\", err)\n}","preventionTips":["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\""],"tags":["os-release","os-detection","filesystem","linux"],"backgroundTag":"os-release-not-found","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}