kubernetes/kops · error

failed to read %s: %w

Error message

failed to read %s: %w

What it means

disableSwap reads /etc/fstab with os.ReadFile to strip swap entries; if that read fails (file missing, permission denied, I/O error), it returns this wrapped error with the path and the underlying OS error. It is the OS-level precondition check for removing swap on Linode nodes.

Source

Thrown at nodeup/pkg/model/linode.go:62

	// Akamai (Linode) instances ship with swap enabled. Disable it when MemorySwapBehavior is unset,
	// since the default kubelet swap mode (NoSwap) requires swap to be off.
	if b.NodeupConfig.KubeletConfig.MemorySwapBehavior == "" {
		if err := b.disableSwap(c); err != nil {
			return fmt.Errorf("error disabling swap: %v", err)
		}
	}

	return nil
}

// disableSwap disables swap at the OS level and removes swap entries from /etc/fstab
func (b *LinodeBuilder) disableSwap(c *fi.NodeupModelBuilderContext) error {
	// Read current /etc/fstab
	fstabPath := "/etc/fstab"
	fstabBytes, err := os.ReadFile(fstabPath)
	if err != nil {
		return fmt.Errorf("failed to read %s: %w", fstabPath, err)
	}

	// Filter out swap entries
	var filteredLines []string
	scanner := bufio.NewScanner(bytes.NewReader(fstabBytes))
	for scanner.Scan() {
		line := scanner.Text()
		// Keep lines that don't contain " swap " or "\tswap\t"
		if !strings.Contains(line, " swap ") && !strings.Contains(line, "\tswap\t") {
			filteredLines = append(filteredLines, line)
		} else {
			klog.V(2).Infof("Removing swap entry from fstab: %s", line)
		}
	}
	if err := scanner.Err(); err != nil {
		return fmt.Errorf("error reading fstab: %w", err)
	}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Create a valid /etc/fstab on the image (even an empty or comment-only file) before nodeup runs
  2. Fix /etc/fstab permissions so nodeup's user can read it (typically root-readable, e.g. 0644)
  3. Check the wrapped %w error for the exact errno (ENOENT vs EACCES) and act accordingly
  4. Set kubelet memorySwapBehavior to skip the fstab-rewriting path

Example fix

// before: minimal image without fstab
$ ls /etc/fstab
ls: cannot access '/etc/fstab': No such file or directory
// after
$ touch /etc/fstab && chmod 644 /etc/fstab
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat("/etc/fstab")
if err != nil {
    return fmt.Errorf("/etc/fstab must exist and be readable before nodeup: %w", err)
}
if info.IsDir() {
    return fmt.Errorf("/etc/fstab is a directory")
}

Try / catch

fstabBytes, err := os.ReadFile("/etc/fstab")
if err != nil {
    if errors.Is(err, os.ErrNotExist) {
        klog.Warningf("/etc/fstab absent; creating empty one")
        err = os.WriteFile("/etc/fstab", nil, 0644)
    }
    if err != nil {
        return fmt.Errorf("failed to read /etc/fstab: %w", err)
    }
}

Prevention

When it happens

Trigger: os.ReadFile("/etc/fstab") returns an error during nodeup Build on a Linode instance with MemorySwapBehavior unset — e.g. fstab deleted from the image, wrong permissions, or a broken root filesystem.

Common situations: Minimal/custom Linode images that ship without /etc/fstab; security-hardened images with 0600 perms; containers/chroots where fstab was never created; corrupted disks.

Related errors


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