kubernetes/kops · error

missing keypairID for signer %s

Error message

missing keypairID for signer %s

What it means

newStaticKeystore builds a pinned keystore for a signer, but a signer name was supplied with an empty keypairID, so there is no way to pin a specific keypair. The function refuses to construct a keystore in that state.

Source

Thrown at upup/pkg/fi/nodeup/nodetasks/issue_cert.go:222

	certificate *pki.Certificate
	key         *pki.PrivateKey
}

// FindPrimaryKeypair implements pki.Keystore
func (s staticKeystore) FindPrimaryKeypair(ctx context.Context, name string) (*pki.Certificate, *pki.PrivateKey, error) {
	if name != s.keyset {
		return nil, nil, fmt.Errorf("wrong signer: expected %q got %q", s.keyset, name)
	}
	return s.certificate, s.key, nil
}

func newStaticKeystore(ctx context.Context, signer string, keypairID string, keystore fi.KeystoreReader) (pki.Keystore, error) {
	if signer == "" {
		return nil, nil
	}

	if keypairID == "" {
		return nil, fmt.Errorf("missing keypairID for signer %s", signer)
	}

	keyset, err := keystore.FindKeyset(ctx, signer)
	if err != nil {
		return nil, fmt.Errorf("reading keyset for %s: %v", signer, err)
	}
	if keyset == nil {
		return nil, fmt.Errorf("keyset %q not found", signer)
	}

	item := keyset.Items[keypairID]
	if item == nil {
		return nil, fmt.Errorf("no keypair with id %s for %s", keypairID, signer)
	}

	return &staticKeystore{
		keyset:      signer,
		certificate: item.Certificate,

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Ensure the IssueCert task's KeypairID is populated from the keyset's primary item
  2. Re-run kops upgrade/apply so the keypair ID is persisted into the task
  3. If legacy, re-issue the certificate so a keypair ID is selected
  4. Check that the cluster state store is intact and not missing keyset metadata

Example fix

// before
issueCertTask.Signer = fi.String("kubernetes-ca") // KeypairID left nil
// after
issueCertTask.KeypairID = fi.String(primaryKeypairID) // from keyset.Primary.ID
Defensive patterns

Strategy: validation

Validate before calling

if signer != "" && keypairID == "" {
  return fmt.Errorf("signer %s set but keypairID missing; run kops update cluster to persist it", signer)
}

Try / catch

ks, err := newStaticKeystore(ctx, signer, keypairID, keystore)
if err != nil && strings.HasPrefix(err.Error(), "missing keypairID") {
  // fall back to resolving the keyset's primary item id, then retry
}

Prevention

When it happens

Trigger: Run() of the IssueCert task calls newStaticKeystore(ctx, signer, keypairID, keystore) with Signer set but KeypairID empty (task never recorded which keypair to use).

Common situations: Cluster created before keypair IDs were tracked, or task store lost the keypairID after an upgrade/restore; cert task built programmatically without setting KeypairID.

Related errors


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