ahmetb/kubectx · error

failed to seek in file: %w

Error message

failed to seek in file: %w

What it means

kubeconfigFile.Reset calls Truncate(0) then Seek(0, 0) to reposition the file offset at the start before rewriting. This error wraps any Seek failure; it happens after truncation, so the file may already be empty when this error surfaces.

Source

Thrown at internal/kubeconfig/kubeconfigloader.go:68

				continue
			}
			return nil, fmt.Errorf("failed to open file %q: %w", p, err)
		}
		files = append(files, &kubeconfigFile{File: f, path: p})
	}
	if len(files) == 0 {
		return nil, fmt.Errorf("kubeconfig file not found: %w",
			&os.PathError{Op: "open", Path: paths[0], Err: os.ErrNotExist})
	}
	return files, nil
}

func (kf *kubeconfigFile) Reset() error {
	if err := kf.Truncate(0); err != nil {
		return fmt.Errorf("failed to truncate file: %w", err)
	}
	if _, err := kf.Seek(0, 0); err != nil {
		return fmt.Errorf("failed to seek in file: %w", err)
	}
	return nil
}

func kubeconfigPaths() ([]string, error) {
	// KUBECONFIG env var
	if v := os.Getenv("KUBECONFIG"); v != "" {
		return filepath.SplitList(v), nil
	}

	// default path
	home := cmdutil.HomeDir()
	if home == "" {
		return nil, errors.New("HOME or USERPROFILE environment variable not set")
	}
	return []string{filepath.Join(home, ".kube", "config")}, nil
}

View on GitHub (pinned to 12ad6fb22e)

Solutions

  1. Check the wrapped error — "file already closed" means another path closed the handle; remove the duplicate Close
  2. Ensure Reset and Save run sequentially from one owner of the file handle, not concurrently
  3. Verify the file is a regular file (special devices may not support seek)
  4. Reload the kubeconfig from disk (construct a new loader) if the handle is in an unknown state

Example fix

// before
go k.Close()
k.Save()   // handle closed mid-way; seek fails
// after
if err := k.Save(); err != nil { return err }
if err := k.Close(); err != nil { return err }
Defensive patterns

Strategy: try-catch

Validate before calling

// Go
// Ensure the handle is still valid before Reset
if _, err := kf.Seek(0, io.SeekCurrent); err != nil {
    return fmt.Errorf("kubeconfig handle invalid: %w", err)
}

Type guard

func isClosedErr(err error) bool {
    return errors.Is(err, os.ErrClosed)
}

Try / catch

if err := kf.Reset(); err != nil {
    if errors.Is(err, os.ErrClosed) {
        return fmt.Errorf("kubeconfig file handle already closed — reload before saving: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling Reset when the underlying file descriptor is invalid or already closed, causing os.File.Seek to fail (the underlying error is an *os.PathError with Op "seek").

Common situations: Double-close of the shared *os.File from concurrent code paths; using a file opened against a special file/device that does not support seeking; file descriptor corruption after an earlier I/O failure.

Related errors


AI-assisted analysis of ahmetb/kubectx@12ad6fb22e (2026-09-02). Data as JSON: /api/errors/2c9dd64671db4899. Report an issue: GitHub.