kubernetes/kops · error
unable to find specified SSH key %q
Error message
unable to find specified SSH key %q
What it means
When DescribeKeyPairs returns no key pairs at all and the task is marked as referencing an existing key (IsExistingKey) with a non-empty name, kOps fails with "unable to find specified SSH key". This protects against silently creating a new key when the user explicitly said the key already exists.
Source
Thrown at upup/pkg/fi/cloudup/awstasks/sshkey.go:74
func (e *SSHKey) Find(c *fi.CloudupContext) (*SSHKey, error) {
cloud := awsup.GetCloud(c)
return e.find(c.Context(), cloud)
}
func (e *SSHKey) find(ctx context.Context, cloud awsup.AWSCloud) (*SSHKey, error) {
request := &ec2.DescribeKeyPairsInput{
KeyNames: []string{fi.ValueOf(e.Name)},
}
response, err := cloud.EC2().DescribeKeyPairs(ctx, request)
if err != nil && awsup.AWSErrorCode(err) != "InvalidKeyPair.NotFound" {
return nil, fmt.Errorf("error listing SSHKeys: %v", err)
}
if response == nil || len(response.KeyPairs) == 0 {
if e.IsExistingKey() && *e.Name != "" {
return nil, fmt.Errorf("unable to find specified SSH key %q", *e.Name)
}
return nil, nil
}
if len(response.KeyPairs) != 1 {
return nil, fmt.Errorf("Found multiple SSHKeys with Name %q", *e.Name)
}
k := response.KeyPairs[0]
actual := &SSHKey{
ID: k.KeyPairId,
Name: k.KeyName,
KeyFingerprint: k.KeyFingerprint,
Tags: mapEC2TagsToMap(k.Tags),
Shared: e.Shared,
}
// Avoid spurious changesView on GitHub (pinned to 4c8573c808)
Solutions
- Correct the key name in the cluster spec (kops get instancegroups / cluster.yaml).
- Verify the key exists: aws ec2 describe-key-pairs --key-names <name> in the target region.
- Import the key if missing: aws ec2 import-key-pair --key-name <name> --public-key-material fileb://id_rsa.pub.
- Switch the cluster to a different key or drop the existing-key flag so kOps creates one.
Example fix
// before (cluster spec) sshKeyName: "admin-prod-key" // after sshKeyName: "admin-staging-key" // name that exists in the target region
Defensive patterns
Strategy: validation
Validate before calling
keyName := spec.SSHKeyName
out, err := exec.Command("aws", "ec2", "describe-key-pairs",
"--region", region, "--key-names", keyName).Output()
if err != nil {
return fmt.Errorf("SSH key %q does not exist in %s; import it or fix the spec", keyName, region)
} Type guard
func keyExistsInRegion(keyName, region string) bool {
out, err := exec.Command("aws", "ec2", "describe-key-pairs", "--region", region, "--key-names", keyName).Output()
return err == nil && len(out) > 0
} Prevention
- Verify key names with aws ec2 describe-key-pairs in the target region before setting them in specs.
- Remember keys are region-scoped; don't reuse names across regions assuming they exist.
- Import keys with aws ec2 import-key-pair before referencing them.
- Keep key names centralized in one config to avoid typos.
When it happens
Trigger: Spec sets an SSH key by name with existing semantics, but no EC2 key pair with that exact name exists in the target region/account.
Common situations: Typo in the SSH key name in the cluster spec; key exists in a different region; key was deleted out-of-band; running kOps against a different account than where the key was created.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- found no ElasticIPs for: %v
- error listing SSHKeys: %v
- Found multiple SSHKeys with Name %q
- error creating SSHKey: %v
- could not find Image for %q
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/1d347c1071099a63.
Report an issue: GitHub.