{"record":{"id":"1edd708f5b659192","repo":"kubernetes/kops","slug":"error-reading-user-provided-private-key-q-v","errorCode":null,"errorMessage":"error reading user provided private key %q: %v","messagePattern":"error reading user provided private key %q: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/kops/create_keypair.go","lineNumber":193,"sourceCode":"\tfor name := range keysets {\n\t\tif rotatableKeysetFilter(name, nil) {\n\t\t\tif err := createKeypair(ctx, out, options, name, keyStore); err != nil {\n\t\t\t\treturn fmt.Errorf(\"creating keypair for %s: %v\", name, err)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc createKeypair(ctx context.Context, out io.Writer, options *CreateKeypairOptions, name string, keyStore fi.CAStore) error {\n\tvar err error\n\tvar privateKey *pki.PrivateKey\n\tif options.PrivateKeyPath != \"\" {\n\t\toptions.PrivateKeyPath = utils.ExpandPath(options.PrivateKeyPath)\n\t\tprivateKeyBytes, err := os.ReadFile(options.PrivateKeyPath)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error reading user provided private key %q: %v\", options.PrivateKeyPath, err)\n\t\t}\n\n\t\tprivateKey, err = pki.ParsePEMPrivateKey(privateKeyBytes)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error loading private key %q: %v\", privateKeyBytes, err)\n\t\t}\n\t}\n\n\tvar cert *pki.Certificate\n\tif options.CertPath == \"\" {\n\t\tif privateKey == nil {\n\t\t\tprivateKey, err = pki.GeneratePrivateKey()\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error generating private key: %v\", err)\n\t\t\t}\n\t\t}\n\n\t\tserial := pki.BuildPKISerial(time.Now().UnixNano())","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/cmd/kops/create_keypair.go#L175-L211","documentation":"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.","triggerScenarios":"`kops create keypair <cluster> --keyset <name> --key <path>` where os.ReadFile(<expanded path>) errors (cmd/kops/create_keypair.go:193).","commonSituations":"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.","solutions":["Verify the file exists at the expanded path: ls -l <path>.","Fix file permissions (chmod so the invoking user can read it).","Use an absolute path instead of ~ to avoid expansion surprises in CI.","Check secrets mounting when running inside containers/pipelines."],"exampleFix":"// before\nkops create keypair cluster.k8s.local --keyset ca --key ~/keys/ca.key   # file not there\n// after\nls -l /home/me/keys/ca.key  # confirm first\nkops create keypair cluster.k8s.local --keyset ca --key /home/me/keys/ca.key","handlingStrategy":"validation","validationCode":"KEY_PATH=$(readlink -f \"${KEY_PATH/#\\~/$HOME}\")\n[[ -f \"$KEY_PATH\" && -r \"$KEY_PATH\" ]] || { echo \"private key not readable: $KEY_PATH\"; exit 1; }\nkops create keypair \"$CLUSTER\" --keyset ca --key \"$KEY_PATH\"","typeGuard":null,"tryCatchPattern":"if ! out=$(kops create keypair \"$CLUSTER\" --keyset ca --key \"$KEY\" 2>&1); then\n  case \"$out\" in\n    *\"error reading user provided private key\"*) echo \"Check path/permissions: $out\";;\n  esac\nfi","preventionTips":["Use absolute paths for --key in scripts and CI.","Verify file existence and permissions before invoking kops.","Mount/copy key material explicitly in containerized runs; don't rely on $HOME."],"tags":["filesystem","private-key","cli","kops"],"backgroundTag":"file-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"}