cilium/cilium · error
PEM format error in TLS Key
Error message
PEM format error in TLS Key
What it means
validateTLSSecret checks that both the TLS certificate and private key stored in a Kubernetes TLS-type Secret are valid PEM-encoded data before the Gateway listener uses them. This error means the Secret's tls.key entry failed helpers.IsValidPemFormat — it is empty, malformed, or not PEM armored. The controller rejects the listener so it is not programmed with an unusable key.
Source
Thrown at operator/pkg/gateway-api/status_listener.go:672
return res
}
func (m *ListenerStatusManager) validateTLSSecret(ctx context.Context, namespace, name string) error {
secret := &corev1.Secret{}
if err := m.client.Get(ctx, client.ObjectKey{
Namespace: namespace,
Name: name,
}, secret); err != nil {
return err
}
if !helpers.IsValidPemFormat(secret.Data[corev1.TLSCertKey]) {
return fmt.Errorf("PEM format error in TLS Certificate")
}
if !helpers.IsValidPemFormat(secret.Data[corev1.TLSPrivateKeyKey]) {
return fmt.Errorf("PEM format error in TLS Key")
}
return nil
}
func (m *ListenerStatusManager) filterOutInvalidListeners(ctx context.Context, listeners []ingestion.ListenerWithContext, grants []gatewayv1.ReferenceGrant) ([]ingestion.ListenerWithContext, []ingestion.ListenerWithContext) {
valid := make([]ingestion.ListenerWithContext, 0, len(listeners))
invalid := make([]ingestion.ListenerWithContext, 0, len(listeners))
for _, listener := range listeners {
res := m.validateListener(ctx, listener.Listener, listenerValidationParams{
ownerNamespace: listener.Source.Namespace,
ownerKind: listener.Source.Kind,
generation: listener.SourceGeneration,
grants: grants,
ownerRef: types.NamespacedName{
Name: listener.Source.Name,
Namespace: listener.Source.Namespace,
}.String(),
})View on GitHub (pinned to ac7b90affa)
Solutions
- Fix the Secret's tls.key field to contain a complete PEM block including -----BEGIN ... PRIVATE KEY----- and -----END ... PRIVATE KEY----- lines
- Recreate the TLS Secret with kubectl create secret tls <name> --cert=cert.pem --key=key.pem
- Verify the certificateRefs on the Gateway listener point to the correct Secret name and namespace
- If using cert-manager, check the Certificate resource status for issuance errors and let it re-issue the key pair
Example fix
// before: key stored without PEM armor
data:
tls.key: MIIJKQIBAAKC... # raw DER, no headers
// after
data:
tls.key: <base64 of full PEM:
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----> Defensive patterns
Strategy: validation
Validate before calling
// Before referencing the Secret in a Gateway listener
for _, k := range []string{"tls.crt", "tls.key"} {
data, ok := secret.Data[k]
if !ok || !bytes.Contains(data, []byte("-----BEGIN ")) {
return fmt.Errorf("secret %s/%s: %s is not PEM encoded", secret.Namespace, secret.Name, k)
}
} Type guard
func hasPEMBlock(data []byte) bool {
block, _ := pem.Decode(data)
return block != nil
} Prevention
- Create TLS Secrets with kubectl create secret tls rather than hand-crafting base64
- Use cert-manager to issue and rotate certificates automatically
- Lint manifests in CI to assert kubernetes.io/tls Secrets contain both keys with PEM markers
- Verify certificateRefs point at the right Secret name/namespace before applying Gateways
When it happens
Trigger: A Secret of type kubernetes.io/tls referenced by a Gateway listener's certificateRefs has a tls.key value that is empty, base64 garbage, truncated, or lacks PEM '-----BEGIN ... PRIVATE KEY-----' markers.
Common situations: Secrets created by cert-manager or manually with a raw key pasted without headers; keys converted to PKCS#8/PKCS#1 without armor; typo of tls.key field name; Secret synced from another namespace without the key portion; whitespace/encoding corruption in GitOps pipelines.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- PEM format error in TLS Certificate
- get secret %q to retrieve CA: %w
- unable to get client secret to access clustermesh service: %
- unable to retrieve the CA certificate: %w
- unable to get CA secret %s/%s: %w
AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31).
Data as JSON: /api/errors/1b5e8cf47d5fe5c6.
Report an issue: GitHub.