hashicorp/terraform · error
failed to create signer from raw private key %q: %s
Error message
failed to create signer from raw private key %q: %s
What it means
Raised in signCertWithPrivateKey when ssh.NewSignerFromKey(rawPk) fails. The private key was successfully parsed by ParseRawPrivateKey, but converting the resulting crypto.PrivateKey into an ssh.Signer failed. This typically indicates the parsed key is of an unsupported or degenerate type for signer creation.
Source
Thrown at internal/communicator/ssh/provisioner.go:410
return conf, nil
}
// Create a Cert Signer and return ssh.AuthMethod
func signCertWithPrivateKey(pk string, certificate string) (ssh.AuthMethod, error) {
rawPk, err := ssh.ParseRawPrivateKey([]byte(pk))
if err != nil {
return nil, fmt.Errorf("failed to parse private key %q: %s", pk, err)
}
pcert, _, _, _, err := ssh.ParseAuthorizedKey([]byte(certificate))
if err != nil {
return nil, fmt.Errorf("failed to parse certificate %q: %s", certificate, err)
}
usigner, err := ssh.NewSignerFromKey(rawPk)
if err != nil {
return nil, fmt.Errorf("failed to create signer from raw private key %q: %s", rawPk, err)
}
ucertSigner, err := ssh.NewCertSigner(pcert.(*ssh.Certificate), usigner)
if err != nil {
return nil, fmt.Errorf("failed to create cert signer %q: %s", usigner, err)
}
return ssh.PublicKeys(ucertSigner), nil
}
func readPrivateKey(pk string) (ssh.AuthMethod, error) {
// We parse the private key on our own first so that we can
// show a nicer error if the private key has a password.
block, _ := pem.Decode([]byte(pk))
if block == nil {
return nil, errors.New("Failed to read ssh private key: no key found")
}
if block.Headers["Proc-Type"] == "4,ENCRYPTED" {View on GitHub (pinned to c9def3e214)
Solutions
- Regenerate the key pair using a standard supported type: RSA (>=2048), ECDSA (P-256/P-384/P-521), or Ed25519.
- Update terraform to a newer version that bundles a newer x/crypto/ssh with broader key support.
- Verify the key file contains a single private key, not a bundle.
- Test the key with ssh-keygen -y -f keyfile to confirm it produces a valid public key.
Example fix
// before
connection {
private_key = file("~/.ssh/exotic_key")
certificate = file("~/.ssh/exotic_key-cert.pub")
}
// after
connection {
private_key = file("~/.ssh/id_ed25519")
certificate = file("~/.ssh/id_ed25519-cert.pub")
} Defensive patterns
Strategy: validation
Validate before calling
// Validate the private key can produce a signer before use
func validateKeyCanSign(pk string) error {
rawPk, err := ssh.ParseRawPrivateKey([]byte(pk))
if err != nil {
return fmt.Errorf("cannot parse private key: %w", err)
}
if _, err := ssh.NewSignerFromKey(rawPk); err != nil {
return fmt.Errorf("key type does not support signing: %w", err)
}
return nil
} Prevention
- Use standard key types (RSA >=2048, ECDSA, Ed25519) supported by Go's SSH library.
- Update terraform to pick up newer x/crypto/ssh for newer key type support.
- Verify the key file contains a single private key, not a bundle.
When it happens
Trigger: ParseRawPrivateKey succeeded (the key is valid PEM) but the resulting key type is not suitable for signing — for example an unsupported curve, a key type the SSH signer does not handle, or a malformed key structure that parses but cannot sign.
Common situations: The private key uses an exotic or very new key type not yet supported by the Go x/crypto/ssh version bundled with terraform, or the key file contains a multi-key bundle where ParseRawPrivateKey returned an unexpected type.
Related errors
- failed to parse private key %q: %s
- failed to create cert signer %q: %s
- failed to parse certificate %q: %s
- Upload failed: %v
- Failed to upload script: %v
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/213503b22cfbe5e7.
Report an issue: GitHub.