{"record":{"id":"e96bf5aa89a0a8be","repo":"kubernetes/kops","slug":"reading-private-key-q-v","errorCode":null,"errorMessage":"reading private key %q: %v","messagePattern":"reading private key %q: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/kops/toolbox_dump.go","lineNumber":164,"sourceCode":"\t\tresourceMap, err := resourceops.ListResources(cloud, cluster)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\td, err := resources.BuildDump(ctx, cloud, resourceMap)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcloudResources = d\n\t}\n\n\tif options.Dir != \"\" {\n\t\tprivateKeyPath := options.PrivateKey\n\t\tif strings.HasPrefix(privateKeyPath, \"~/\") {\n\t\t\tprivateKeyPath = filepath.Join(os.Getenv(\"HOME\"), privateKeyPath[2:])\n\t\t}\n\t\tkey, err := os.ReadFile(privateKeyPath)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"reading private key %q: %v\", privateKeyPath, err)\n\t\t}\n\n\t\tparsedKey, err := ssh.ParseRawPrivateKey(key)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"parsing private key %q: %v\", privateKeyPath, err)\n\t\t}\n\n\t\tsigner, err := ssh.NewSignerFromKey(parsedKey)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"creating signer for private key %q: %v\", privateKeyPath, err)\n\t\t}\n\n\t\tcontextName := cluster.ObjectMeta.Name\n\t\tclientGetter := genericclioptions.NewConfigFlags(true)\n\t\tclientGetter.Context = &contextName\n\n\t\tvar nodes corev1.NodeList\n","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/cmd/kops/toolbox_dump.go#L146-L182","documentation":"When toolbox dump is asked to use a private key (for SSH bastion tunneling), it first reads the key file from disk. This error wraps any os.ReadFile failure — missing file, permission denied, or path issues — with the resolved path and the underlying OS error.","triggerScenarios":"--private-key (options.PrivateKey) is set, the path is expanded (~/*), and os.ReadFile fails: the file does not exist at the resolved path, the user lacks read permission, or the path is a directory.","commonSituations":"Passing a path that only exists on another machine; the '~' expansion fails because $HOME is unset in cron/CI; permissions tightened by SSH tooling (600 on a key owned by another user); pointing at the .pub file or a directory instead of the private key.","solutions":["Check the resolved path printed in the error exists: ls -la <path>.","Fix file permissions: chmod 600 <keyfile> and ensure your user owns it.","Set HOME correctly (or pass an absolute path) when running under cron/CI where ~ cannot expand.","Pass the private key file, not the .pub counterpart, and confirm the underlying OS error (No such file vs permission denied) before further steps."],"exampleFix":"// before\nkops toolbox dump --name c.k8s.local --private-key ~/keys/id_rsa  # HOME unset -> path '/keys/id_rsa' missing\n// after\nkops toolbox dump --name c.k8s.local --private-key /home/me/keys/id_rsa\nchmod 600 /home/me/keys/id_rsa","handlingStrategy":"validation","validationCode":"KEY_PATH=\"${KEY_PATH/#\\~/$HOME}\"\nif [ ! -f \"$KEY_PATH\" ]; then echo \"private key not found: $KEY_PATH\"; exit 1; fi\nif [ ! -r \"$KEY_PATH\" ]; then echo \"private key unreadable (check perms/owner)\"; exit 1; fi","typeGuard":null,"tryCatchPattern":"key, err := os.ReadFile(privateKeyPath)\nif err != nil {\n    return fmt.Errorf(\"reading private key %q (check path, permissions, HOME): %w\", privateKeyPath, err)\n}","preventionTips":["Use absolute paths for keys in CI/cron where $HOME may differ","chmod 600 the key and ensure your user owns it","Never point at the .pub file or a directory","Verify with ssh -i \"$KEY_PATH\" -o BatchMode=yes host true before running dump"],"tags":["kops","ssh","file-io"],"backgroundTag":"private-key-file-missing","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}