kubernetes/kops · error

error reading user provided private key %q: %v

Error message

error reading user provided private key %q: %v

What it means

In createKeypair, when the user supplies --key, the file is expanded (~) and read from disk with os.ReadFile before parsing. Any OS-level read failure (missing file, permission denied, is-a-directory) is wrapped with this message including the resolved path.

Source

Thrown at cmd/kops/create_keypair.go:193

	for name := range keysets {
		if rotatableKeysetFilter(name, nil) {
			if err := createKeypair(ctx, out, options, name, keyStore); err != nil {
				return fmt.Errorf("creating keypair for %s: %v", name, err)
			}
		}
	}

	return nil
}

func createKeypair(ctx context.Context, out io.Writer, options *CreateKeypairOptions, name string, keyStore fi.CAStore) error {
	var err error
	var privateKey *pki.PrivateKey
	if options.PrivateKeyPath != "" {
		options.PrivateKeyPath = utils.ExpandPath(options.PrivateKeyPath)
		privateKeyBytes, err := os.ReadFile(options.PrivateKeyPath)
		if err != nil {
			return fmt.Errorf("error reading user provided private key %q: %v", options.PrivateKeyPath, err)
		}

		privateKey, err = pki.ParsePEMPrivateKey(privateKeyBytes)
		if err != nil {
			return fmt.Errorf("error loading private key %q: %v", privateKeyBytes, err)
		}
	}

	var cert *pki.Certificate
	if options.CertPath == "" {
		if privateKey == nil {
			privateKey, err = pki.GeneratePrivateKey()
			if err != nil {
				return fmt.Errorf("error generating private key: %v", err)
			}
		}

		serial := pki.BuildPKISerial(time.Now().UnixNano())

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Verify the file exists at the expanded path: ls -l <path>.
  2. Fix file permissions (chmod so the invoking user can read it).
  3. Use an absolute path instead of ~ to avoid expansion surprises in CI.
  4. Check secrets mounting when running inside containers/pipelines.

Example fix

// before
kops create keypair cluster.k8s.local --keyset ca --key ~/keys/ca.key   # file not there
// after
ls -l /home/me/keys/ca.key  # confirm first
kops create keypair cluster.k8s.local --keyset ca --key /home/me/keys/ca.key
Defensive patterns

Strategy: validation

Validate before calling

KEY_PATH=$(readlink -f "${KEY_PATH/#\~/$HOME}")
[[ -f "$KEY_PATH" && -r "$KEY_PATH" ]] || { echo "private key not readable: $KEY_PATH"; exit 1; }
kops create keypair "$CLUSTER" --keyset ca --key "$KEY_PATH"

Try / catch

if ! out=$(kops create keypair "$CLUSTER" --keyset ca --key "$KEY" 2>&1); then
  case "$out" in
    *"error reading user provided private key"*) echo "Check path/permissions: $out";;
  esac
fi

Prevention

When it happens

Trigger: `kops create keypair <cluster> --keyset <name> --key <path>` where os.ReadFile(<expanded path>) errors (cmd/kops/create_keypair.go:193).

Common situations: Typo in path; running in container/CI where the key wasn't mounted; wrong $HOME so ~ expansion points elsewhere; file permissions after copying keys between machines.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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