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
- Check the wrapped error — "file already closed" means another path closed the handle; remove the duplicate Close
- Ensure Reset and Save run sequentially from one owner of the file handle, not concurrently
- Verify the file is a regular file (special devices may not support seek)
- 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
- Define strict ownership: only one place closes the file, after all writes
- Avoid concurrent goroutines sharing one kubeconfigFile handle
- Reload from disk if handle state is uncertain instead of reusing it
- Only use regular files for kubeconfigs
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
- failed to open file %q: %w
- failed to truncate file: %w
- kubeconfig error: %w
- failed to get current context: %w
- failed to read namespace of "%s": %w
AI-assisted analysis of ahmetb/kubectx@12ad6fb22e (2026-09-02).
Data as JSON: /api/errors/2c9dd64671db4899.
Report an issue: GitHub.