External Secrets Operator (ESO) lets Kubernetes pull secrets from tools like AWS Secrets Manager, HashiCorp Vault, Azure Key Vault, and OpenBao. When it works, you forget it's even there. When it breaks, your app won't start because a Secret is missing, empty, or old. This guide is a simple runbook for External Secrets Operator troubleshooting.
Fix SecretStore, Auth, and Sync Failures in External Secrets Operator
Table of Contents
- How ESO Reconciliation Actually Works
- Step 1: Confirm the Controller Is Healthy
- Step 2: Read the ExternalSecret Status
- Step 3: Fix a SecretStore That Is Not Ready
- Step 4: Fix Provider Authentication Failures
- Step 5: Fix Missing Keys, Conversion, and Template Errors
- Step 6: Fix Stale Secrets and Refresh Failures
- Step 7: Fix RBAC Problems
- Step 8: Read Controller Events and Logs Together
- Key Commands for External Secrets Operator Troubleshooting
- Keep ESO in an Isolated Environment
- Conclusion

How ESO Reconciliation Actually Works
Before troubleshooting, you need to know the flow ESO follows, because every fix in this guide maps to one step in this loop:
- The controller reads your
ExternalSecretobject. - It looks up the
SecretStoreorClusterSecretStorenamed insecretStoreRef. - It authenticates to the provider using the credentials in that store.
- It fetches the secret value from the provider.
- It applies any
templateor data transformation. - It writes or updates a Kubernetes
Secretobject. - It waits for
refreshInterval, then repeats the loop.
Every error you see in External Secrets Operator troubleshooting comes from one of these seven steps. Once you know which step failed, the fix becomes easy.
Step 1: Confirm the Controller Is Healthy
The first step is always to check that the controller is healthy. If the controller pod is crashing, nothing will work. To check the controller, run the commands below:
Then, check what version is actually running, because mismatched CRD and controller versions cause silent failures:
If the image tag doesn't match your Helm chart version, upgrade the CRDs and controller together using server-side apply. This has been required since v0.19, and it's still required on v2.x, because the CRDs are too big for the old kubectl size limit:
Step 2: Read the ExternalSecret Status
This is the most important step in External Secrets Operator troubleshooting. It is recommended to start with kubectl describe on the ExternalSecret resource:
In the output, you must look for the following fields:
- Conditions → Type: Ready, Status: Should be
True. If it isFalse, read theMessageandReasonfields; they tell you exactly what failed. - Events: Any
Warningevent tells you the error from the last reconcile attempt.
A healthy object looks like this:
A broken one shows Reason: SecretSyncedError, with a message that tells you the cause, like a missing key or an auth failure. This one field saves you the most time in External Secrets Operator troubleshooting, because it names the exact step that failed in the reconciliation loop.
Step 3: Fix a SecretStore That Is Not Ready
If the ExternalSecret event mentions the store, or if you see errors like could not get secret data from provider, check the store itself:
A store stuck in Status: False with Reason: Invalid means one of these three things:
- The provider endpoint in
spec.provideris wrong, such as a bad URL, wrong region, or wrong project ID. - The referenced auth secret does not exist in the namespace ESO expects.
- Network access from the cluster to the provider is blocked, such as a firewall, private endpoint, or DNS.
Test the network path directly from a pod in the same namespace as the controller, since ESO cannot reach providers your cluster network blocks:
If DNS or TCP fails here, the SecretStore will never become Ready, no matter how correct your YAML is.
Step 4: Fix Provider Authentication Failures
Once the store is Ready but the ExternalSecret still fails, the problem depends on authentication. Each provider has its own common failure pattern:
Pull the exact authentication error from the controller logs, filtered by your ExternalSecret's namespace:
For Vault, you must check that the Kubernetes auth role is bound to the correct ServiceAccount and namespace:
Provider authentication failures are the most frequent reason people search for External Secrets Operator troubleshooting help, because the error message from the SDK is generic and does not point to the actual misconfigured field.
Step 5: Fix Missing Keys, Conversion, and Template Errors
If auth succeeds but the ExternalSecret still shows SecretSyncedError, the message names a missing key or a bad template.
Missing key error looks like key not found or secret does not have key <name>. This means the remoteRef.key or remoteRef.property in your ExternalSecret spec does not match what actually exists in the provider. Confirm the exact key name directly in the provider, not from memory:
Conversion or decoding error happens when ESO tries to base64-decode a value that isn't valid base64, or when dataFrom.extract expects JSON but gets plain text instead. Check spec.dataFrom in your ExternalSecret. And if you're pulling multiple keys from one secret, make sure that secret is actually stored as JSON.
Template error shows up as failed to execute template when spec.target.template uses wrong Go template syntax, like pointing to a field name that doesn't exist in the fetched data. Test the template locally before applying it. Always match field names with the real keys returned by dataFrom.extract.
Step 6: Fix Stale Secrets and Refresh Failures
A secret that still shows the old value is one of the most confusing issues in External Secrets Operator troubleshooting. Because the ExternalSecret can report Ready: True while the actual Kubernetes Secret content is old.
First, you must check spec.refreshPolicy. If it is set to CreatedOnce, ESO creates the Secret once and never updates it again. Set it to Periodic, which is the default, if you want ongoing updates.
Second, you must check the refreshTime field to confirm a sync attempt happened recently:
Third, remember that ESO updates the Secret object, not your running pod's environment variables. If your app reads secrets through env or envFrom, it only picks up new values on pod restart. Roll the deployment after a secret rotation if your app does not reload secrets from mounted files:
To force an immediate refresh instead of waiting for refreshInterval, annotate the resource:
For a ClusterExternalSecret, use the namespaced annotation instead:
Step 7: Fix RBAC Problems
RBAC issues show up as forbidden errors in the controller logs, or as an ExternalSecret that never even attempts to reconcile. ESO's own ServiceAccount needs permission to read Secrets and write to ExternalSecret status; this is bundled by the Helm chart by default. So you must check whether someone has overridden the default ClusterRole:
If you use namespace-scoped SecretStore resources with a serviceAccountRef for provider auth, confirm the referenced ServiceAccount exists in the same namespace and has the correct annotations:
A common RBAC mistake in External Secrets Operator troubleshooting is setting up the cloud IAM role correctly, but forgetting to bind it to the right Kubernetes ServiceAccount. ESO actually uses the ServiceAccount named inside the SecretStore, not its own controller ServiceAccount.
Step 8: Read Controller Events and Logs Together
When status conditions don't give you enough detail, you can match the ExternalSecret's Kubernetes events with the controller logs from the same timestamp:
Match the timestamps. The event tells you what the controller decided; the log tells you why. For example, if you see a SecretSyncedError event paired with a log line showing an HTTP 429 from the provider, the real fix is rate limiting or backoff tuning, not a credentials change.
If reconciliation seems to loop endlessly without settling, check whether the provider's error message keeps changing slightly on every attempt. This is a known issue with some providers, and it forces ESO to keep retrying instead of reaching a stable Ready state. Once you fix the provider-side issue, restarting the controller pod clears a stuck reconcile loop:
Key Commands for External Secrets Operator Troubleshooting
Once you've found the failing step, these are the exact commands to check it, fix it, or force a retry. Save these commands as your quick reference for everyday ESO work:
Keep ESO in an Isolated Environment
Provider auth and network errors are hard to diagnose when your cluster shares noisy traffic or unpredictable DNS with other workloads. You can use an isolated PerLod environment to keep secret-provider networking and cluster traffic predictable.
Explore dedicated server hosting at PerLod for an isolated environment to run and test your Kubernetes and ESO setup.
Conclusion
External Secrets Operator troubleshooting depends on checking things in order. Most failures appear in the status field before you ever need to touch the provider logs.
If you're setting up ESO from scratch, you can follow our guide to the External Secrets Operator with OpenBao. Then, use this runbook for when something breaks.
Your refreshPolicy may be set to CreatedOnce, or your pod is not restarting to pick up the new environment variables.
Add or update the force-sync annotation on the ExternalSecret with kubectl annotate.
Because of a wrong provider URL, a missing auth secret, or a blocked network path to the provider.
Wrong IAM role, expired token, wrong Vault auth role, or a ServiceAccount that is not bound correctly.