kubernetes/kops · error

private key not found

Error message

private key %q not found

What it means

The keyset item exists (and has a certificate when requested) but item.PrivateKey is nil, so buildCertificatePairTask cannot write the .key file. Only the certificate half of the keypair is present in the keystore.

Solutions

  1. Verify the keypair includes a private key via `kops get keypairs <name> -o yaml`; re-issue with `kops create keypair <name>` if missing
  2. If this is a public-only keyset, switch the builder call to BuildCertificateTask (cert only) instead of BuildCertificatePairTask/BuildPrivateKeyTask
  3. Restore the private key from backup or re-create the keyset in the state store
  4. Check that the requested keypair ID isn't pointing at a cert-only item in keyset.Items
Defensive patterns

Strategy: validation

Validate before calling

item := keyset.Items[keypairID]
if item == nil || item.PrivateKey == nil {
    return fmt.Errorf("keypair %s/%s has no private key; use BuildCertificateTask for cert-only keysets or re-issue", name, keypairID)
}

Try / catch

if err := c.BuildPrivateKeyTask(ctx, name, path, filename, owner, nil); err != nil {
    if strings.Contains(err.Error(), "private key") {
        klog.Errorf("keyset %s lacks a private key; ensure it was created with 'kops create keypair'", name)
    }
    return err
}

Prevention

When it happens

Trigger: item.PrivateKey is nil in BuildCertificatePairTask or BuildPrivateKeyTask — keypair items that contain only a public certificate (e.g. CA keysets imported without private keys, or the CA's private key intentionally withheld) being used where a private key file is required.

Common situations: CA keysets whose private keys are stored only on control-plane / never distributed; state-store restore keeping public parts only; writing private-key files for a keyset that legitimately has no private key.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/7d9a37deec0c4956. Report an issue: GitHub.

Appendix: source

Thrown at nodeup/pkg/model/context.go:428

		cert, err := certificate.AsString()
		if err != nil {
			return err
		}

		ctx.AddTask(&nodetasks.File{
			Path:           p + ".crt",
			Contents:       fi.NewStringResource(cert),
			Type:           nodetasks.FileType_File,
			Mode:           s("0600"),
			Owner:          owner,
			BeforeServices: beforeServices,
		})
	}

	privateKey := item.PrivateKey
	if privateKey == nil {
		return fmt.Errorf("private key %q not found", name)
	}

	key, err := privateKey.AsString()
	if err != nil {
		return err
	}

	ctx.AddTask(&nodetasks.File{
		Path:     p + ".key",
		Contents: fi.NewStringResource(key),
		Type:     nodetasks.FileType_File,
		Mode:     s("0600"),
		Owner:    owner,
	})

	return nil
}

View on GitHub (pinned to 4c8573c808)