istio/istio · error

secret %v/%v not found

Error message

secret %v/%v not found

What it means

Returned by CredentialsController.GetCertInfo when the informer cache lookup s.secrets.Get(name, namespace) returns nil: no Kubernetes Secret with that name exists (or has reached the cache) in the namespace. This is the leaf-certificate lookup used for Gateway credentialName and similar SDS pushes.

Source

Thrown at pilot/pkg/credentials/kube/secrets.go:222

				User: user,
			},
		}, metav1.CreateOptions{})
		if err != nil {
			return err
		}
		if !resp.Status.Allowed {
			return fmt.Errorf("%s/%s is not authorized to read secrets: %v", serviceAccount, namespace, resp.Status.Reason)
		}
		return nil
	}()
	s.insertCache(user, err)
	return err
}

func (s *CredentialsController) GetCertInfo(name, namespace string) (certInfo *credentials.CertInfo, err error) {
	k8sSecret := s.secrets.Get(name, namespace)
	if k8sSecret == nil {
		return nil, fmt.Errorf("secret %v/%v not found", namespace, name)
	}

	return ExtractCertInfo(k8sSecret)
}

func (s *CredentialsController) GetCaCert(name, namespace string) (certInfo *credentials.CertInfo, err error) {
	k8sSecret := s.secrets.Get(name, namespace)
	if k8sSecret == nil {
		strippedName := strings.TrimSuffix(name, securitymodel.SdsCaSuffix)
		// Could not fetch cert, look for secret without -cacert suffix
		k8sSecret := s.secrets.Get(strippedName, namespace)
		if k8sSecret == nil {
			return nil, fmt.Errorf("secret %v/%v not found", namespace, strippedName)
		}
		return ExtractRoot(k8sSecret.Data)
	}
	return ExtractRoot(k8sSecret.Data)
}

View on GitHub (pinned to 8dc789c5cf)

Solutions

  1. Create the referenced secret in the correct namespace: kubectl create secret tls <name> -n <gateway-ns> --cert=... --key=...
  2. Verify name and namespace spelling against the Gateway's credentialName and the gateway's own namespace
  3. If just created, allow the informer a moment to sync; istiod will push the config once the secret appears (secret handlers re-trigger)
  4. For cross-namespace credentials remember the lookup is namespace-scoped — put the secret in the Gateway's namespace

Example fix

# before: Gateway references a missing secret
credentialName: wildcard-tls

# after: create it in the Gateway's namespace
kubectl -n istio-system create secret tls wildcard-tls \
  --cert=./tls.crt --key=./tls.key
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the secret is present in the informer before pushing config.
if s.secrets.Get(name, namespace) == nil {
    return nil, fmt.Errorf("secret %v/%v not found; refusing to reference it", namespace, name)
}
info, err := s.GetCertInfo(name, namespace)

Prevention

When it happens

Trigger: A Gateway (or other consumer) references credentialName=<secret name> and the Secret is absent from the namespace istiod searches (typically the Gateway's own namespace or the configured credential namespace). Also transient when the Secret was just created and the informer has not synced it yet.

Common situations: cert-manager or manual TLS secret not yet created when the Gateway is applied; secret created in the wrong namespace (e.g. default instead of istio-system/gateway ns); typo in credentialName; secret deleted and the gateway config not updated.

Related errors


AI-assisted analysis of istio/istio@8dc789c5cf (2026-08-15). Data as JSON: /api/errors/c28c95deddca4a12. Report an issue: GitHub.