{"record":{"id":"61ca292a8ae534e8","repo":"hashicorp/terraform","slug":"failed-to-read-ssh-private-key-no-key-found","errorCode":null,"errorMessage":"Failed to read ssh private key: no key found","messagePattern":"Failed to read ssh private key: no key found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/communicator/ssh/provisioner.go","lineNumber":426,"sourceCode":"\tusigner, err := ssh.NewSignerFromKey(rawPk)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create signer from raw private key %q: %s\", rawPk, err)\n\t}\n\n\tucertSigner, err := ssh.NewCertSigner(pcert.(*ssh.Certificate), usigner)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create cert signer %q: %s\", usigner, err)\n\t}\n\n\treturn ssh.PublicKeys(ucertSigner), nil\n}\n\nfunc readPrivateKey(pk string) (ssh.AuthMethod, error) {\n\t// We parse the private key on our own first so that we can\n\t// show a nicer error if the private key has a password.\n\tblock, _ := pem.Decode([]byte(pk))\n\tif block == nil {\n\t\treturn nil, errors.New(\"Failed to read ssh private key: no key found\")\n\t}\n\tif block.Headers[\"Proc-Type\"] == \"4,ENCRYPTED\" {\n\t\treturn nil, errors.New(\n\t\t\t\"Failed to read ssh private key: password protected keys are\\n\" +\n\t\t\t\t\"not supported. Please decrypt the key prior to use.\")\n\t}\n\n\tsigner, err := ssh.ParsePrivateKey([]byte(pk))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"Failed to parse ssh private key: %s\", err)\n\t}\n\n\treturn ssh.PublicKeys(signer), nil\n}\n\nfunc connectToAgent(connInfo *connectionInfo) (*sshAgent, error) {\n\tif !connInfo.Agent {\n\t\t// No agent configured","sourceCodeStart":408,"sourceCodeEnd":444,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/communicator/ssh/provisioner.go#L408-L444","documentation":"Returned by `readPrivateKey` when `pem.Decode` of the configured SSH private key material returns a nil block — the supplied key string is not valid PEM (no `-----BEGIN ... -----` block at all). This is checked before password/encryption handling so the user gets a clear 'no key found' message rather than a cryptic parse error.","triggerScenarios":"`connection.private_key` (or the configured key path's contents) cannot be PEM-decoded: empty string, wrong variable interpolated, a public key pasted instead of a private key, or a file read error produced empty content.","commonSituations":"Passing `file(\"id_rsa.pub\")` instead of the private key; a `${var.private_key}` that resolves to empty; copy-paste that dropped the BEGIN/END lines; trailing whitespace/formatting mangled the PEM.","solutions":["Verify the value is an unencrypted PEM private key (starts with `-----BEGIN OPENSSH PRIVATE KEY-----` or RSA/EC PRIVATE KEY).","Check the `private_key`/`private_key_path` interpolation points at the private, not public, key.","Ensure the file read or variable actually contains the key (no trailing newline issues, not empty)."],"exampleFix":"# before\nconnection { type = \"ssh\" private_key = file(\"~/.ssh/id_rsa.pub\") }  # public key -> error\n# after\nconnection { type = \"ssh\" private_key = file(\"~/.ssh/id_rsa\") }","handlingStrategy":"validation","validationCode":"// Validate the key parses as PEM before handing it to the connection:\nif block, _ := pem.Decode([]byte(key)); block == nil {\n    return errors.New(\"private_key is not valid PEM\")\n}","typeGuard":"// isValidPEMPrivateKey reports whether s decodes to a PEM block.\nfunc isValidPEMPrivateKey(s string) bool {\n    block, _ := pem.Decode([]byte(s))\n    return block != nil\n}","tryCatchPattern":"if _, err := readPrivateKey(privateKey); err != nil {\n    return fmt.Errorf(\"invalid ssh private_key for connection: %w\", err)\n}","preventionTips":["Validate private_key content in a `check`/precondition before apply.","Reference private keys, not public keys, in `connection.private_key`.","Store keys in a secrets backend and interpolate; avoid hand-pasting that drops PEM headers."],"tags":["ssh","private-key","pem","connection","provisioner","config"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}