istio/istio · error
no %q data found
Error message
no %q data found
What it means
The sentinel errMissingRootCAKey in istioctl/pkg/multicluster/remote_secret.go: the token secret passed to createRemoteSecretFromPlugin does not contain the 'ca.crt' key (v1.ServiceAccountRootCAKey). It is thrown by tokenDataFromSecret when the secret exists but its Data map lacks the root CA entry.
Source
Thrown at istioctl/pkg/multicluster/remote_secret.go:216
authProviderConfig *api.AuthProviderConfig,
) (*v1.Secret, error) {
caData, ok := tokenSecret.Data[v1.ServiceAccountRootCAKey]
if !ok {
return nil, errMissingRootCAKey
}
// Create a Kubeconfig to access the remote cluster using the auth provider plugin.
kubeconfig := createPluginKubeconfig(caData, clusterName, server, tlsServerName, authProviderConfig)
if err := clientcmd.Validate(*kubeconfig); err != nil {
return nil, fmt.Errorf("invalid kubeconfig: %v", err)
}
// Encode the Kubeconfig in a secret that can be loaded by Istio to dynamically discover and access the remote cluster.
return createRemoteServiceAccountSecret(kubeconfig, clusterName, secName)
}
var (
errMissingRootCAKey = fmt.Errorf("no %q data found", v1.ServiceAccountRootCAKey)
errMissingTokenKey = fmt.Errorf("no %q data found", v1.ServiceAccountTokenKey)
)
func createRemoteSecretFromTokenAndServer(
client kube.CLIClient, tokenSecret *v1.Secret, clusterName, server, tlsServerName, secName string,
) (*v1.Secret, error) {
caData, token, err := waitForTokenData(client, tokenSecret)
if err != nil {
return nil, err
}
// Create a Kubeconfig to access the remote cluster using the remote service account credentials.
kubeconfig := createBearerTokenKubeconfig(caData, token, clusterName, server, tlsServerName)
if err := clientcmd.Validate(*kubeconfig); err != nil {
return nil, fmt.Errorf("invalid kubeconfig: %v", err)
}
// Encode the Kubeconfig in a secret that can be loaded by Istio to dynamically discover and access the remote cluster.View on GitHub (pinned to 8dc789c5cf)
Solutions
- Inspect the secret: `kubectl get secret <name> -o jsonpath='{.data}'` — confirm ca.crt exists.
- If keys are missing, delete the manually created token secret and let the tool recreate it, then retry.
- On k8s >= 1.24, create a projected token via `kubectl create token` or a TokenRequest, or use a secret manifest of type kubernetes.io/service-account-token with the kubernetes.io/service-account.name annotation.
- Point --secret-name at a genuine service-account-token secret.
Example fix
# before: secret exists but is opaque
type: Opaque
# after: properly typed SA token secret the tool can read
apiVersion: v1
kind: Secret
metadata:
name: istio-reader-istio-remote-secret-token
annotations:
kubernetes.io/service-account.name: istio-reader
type: kubernetes.io/service-account-token Defensive patterns
Strategy: validation
Validate before calling
// Check the required keys before handing the secret to the plugin path
func hasRootCA(secret *corev1.Secret) bool {
d, ok := secret.Data[corev1.ServiceAccountRootCAKey]
return ok && len(d) > 0
}
if !hasRootCA(tokenSecret) {
return nil, fmt.Errorf("secret %s lacks %s; wait for token controller or use a projected token",
tokenSecret.Name, corev1.ServiceAccountRootCAKey)
} Type guard
func isMissingRootCA(err error) bool {
return err != nil && strings.Contains(err.Error(),
fmt.Sprintf("no %q data found", corev1.ServiceAccountRootCAKey))
} Try / catch
caData, err := tokenDataFromSecret(secret)
if err != nil {
if isMissingRootCA(err) {
// poll like waitForTokenData does for the bearer path
time.Sleep(2 * time.Second)
caData, err = tokenDataFromSecret(secret)
}
if err != nil {
return nil, err
}
} Prevention
- Only reference secrets of type kubernetes.io/service-account-token.
- Right after creating a token secret, poll for both ca.crt and token keys before use.
- On k8s >= 1.24 mint tokens via TokenRequest instead of expecting auto-populated secrets.
When it happens
Trigger: The service-account token secret referenced (found by listing, by --secret-name, or just created) has no Data["ca.crt"] — either it is not really a kubernetes.io/service-account-token secret, or the API server has not yet populated the projected keys.
Common situations: Race right after secret creation where kube-controller-manager has not stamped ca.crt/token yet (the code has waitForTokenData for the bearer path but the plugin path reads directly); pointing --secret-name at an opaque/TLS secret; k8s 1.24+ where legacy auto-generated SA secrets no longer exist; secret created from a manifest without the token controller.
Related errors
- secret %s/%s does not reference ServiceAccount %s
- could not get specified secret %s/%s: %v
- provided secret does not exist: %s
- failed listing secrets in %s: %v
- no secret found in the service account: %s
AI-assisted analysis of istio/istio@8dc789c5cf (2026-08-15).
Data as JSON: /api/errors/3dbfdc54c30867dd.
Report an issue: GitHub.