kubernetes/kops · error

AsBytes called on nil private key

Error message

AsBytes called on nil private key

What it means

PrivateKey.AsBytes() is a nil-receiver guard: since AsBytes is commonly invoked from Go templates where a nil *PrivateKey can slip through silently, the method explicitly returns this error instead of panicking when called on a nil pointer. It means the code path reached serialization without ever having loaded, generated, or assigned a key.

Source

Thrown at pkg/pki/privatekey.go:96

func (k *PrivateKey) AsString() (string, error) {
	// Nicer behaviour because this is called from templates
	if k == nil {
		return "", fmt.Errorf("AsString called on nil private key")
	}

	var data bytes.Buffer
	_, err := k.WriteTo(&data)
	if err != nil {
		return "", fmt.Errorf("error writing SSL private key: %v", err)
	}
	return data.String(), nil
}

func (k *PrivateKey) AsBytes() ([]byte, error) {
	// Nicer behaviour because this is called from templates
	if k == nil {
		return nil, fmt.Errorf("AsBytes called on nil private key")
	}

	var data bytes.Buffer
	_, err := k.WriteTo(&data)
	if err != nil {
		return nil, fmt.Errorf("error writing SSL PrivateKey: %v", err)
	}
	return data.Bytes(), nil
}

func (k *PrivateKey) UnmarshalJSON(b []byte) (err error) {
	s := ""
	if err := json.Unmarshal(b, &s); err == nil {
		r, err := parsePEMPrivateKey([]byte(s))
		if err != nil {
			// Alternative form: Check if base64 encoded
			// TODO: Do we need this?  I think we need this only on nodeup, but maybe we could just not base64-it?
			d, err2 := base64.StdEncoding.DecodeString(s)

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check for nil before calling: if k == nil or k.Key == nil, generate a key first (GeneratePrivateKey) or return a clear upstream error.
  2. Verify ParsePEMPrivateKey results: it returns (nil, nil) when input is empty — treat nil key as an error at load time instead of passing it along.
  3. Ensure the struct field holding *PrivateKey is populated before template rendering / serialization runs.

Example fix

// before
key, _ := pki.ParsePEMPrivateKey(data)
out, _ := key.AsBytes()
// after
key, err := pki.ParsePEMPrivateKey(data)
if err != nil { return err }
if key == nil { return fmt.Errorf("no private key present in input") }
out, err := key.AsBytes()
if err != nil { return err }
Defensive patterns

Strategy: type-guard

Validate before calling

if key == nil || key.Key == nil {
    return fmt.Errorf("private key not initialized")
}

Type guard

func hasKey(k *pki.PrivateKey) bool { return k != nil && k.Key != nil }

Try / catch

b, err := key.AsBytes()
if err != nil {
    return fmt.Errorf("serializing private key: %w", err)
}

Prevention

When it happens

Trigger: Calling AsBytes() on a *PrivateKey that is nil, e.g. a struct field never populated after ParsePEMPrivateKey returned (nil, nil) for empty input, or a template referencing {{ .Key.AsBytes }} where .Key was never set.

Common situations: Templating (yaml/gotemplate) rendering of resources whose key material was not generated because generation was skipped in dry-run; callers ignoring that ParsePEMPrivateKey can return a nil key with nil error on empty data; keys dropped during struct copy or partial initialization.

Related errors


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