docker-credential-desktop not installed or not available in PATH
Fix "docker-credential-desktop not installed": remove credsStore from ~/.docker/config.json or install a helper. Covers CI and the Kubernetes variant.
error getting credentials - err: exec: "docker-credential-desktop": executable file not found in $PATH, out: ``
Incident Overview
Fix "docker-credential-desktop not installed": remove credsStore from ~/.docker/config.json or install a helper. Covers CI and the Kubernetes variant.
easy fix·5 min read
By Vishvesh Patel·DevOps Engineer·Updated 21 September 2026
error getting credentials - err: exec: "docker-credential-desktop": executable file not found in $PATH, out: `` docker-credential-desktop not installed or not available in PATH error getting credentials - err: exec: "docker-credential-osxkeychain": executable file not found in $PATH
Do this first3 steps
Run these in order. Each one tells you what its output means before you change anything.
• Look at what the config is asking for
The credsStore value names a binary Docker expects to find as docker-credential-<value> on PATH. If that binary is gone, every registry operation fails before it even reaches the network.
• Check whether the helper binary exists
Substitute your own credsStore value. Missing means either the tool that provided it was uninstalled, or you are on a machine that never had it, such as a CI runner using a copied config.
• Remove the credsStore line and log in again
Without credsStore, Docker falls back to storing credentials base64-encoded in config.json. That works everywhere and is less secure, so re-run docker login afterwards and understand the tradeoff.
Docker does not store registry credentials itself when a credential helper is configured. It shells out to an external binary. ~/.docker/config.json names it:
credsStore: "desktop" means Docker will run docker-credential-desktop. If that binary is not on PATH, every pull, push and login fails immediately, before any network request.
cat ~/.docker/config.json
Confirm it
The helper name is always docker-credential- plus the credsStore value:
cat ~/.docker/config.json which docker-credential-desktop || echo "NOT ON PATH"
How you get here
Uninstalled Docker Desktop. You moved to Colima, Rancher Desktop, Podman or plain Docker Engine. The config stayed behind and still points at desktop.
A copied config in CI. Someone committed ~/.docker/config.json or baked it into an image. The runner has no Docker Desktop, so the helper is missing.
A tool reading your config. minikube, Skaffold, Tilt, Testcontainers and various build tools all read ~/.docker/config.json. They hit this even when docker itself is fine, which makes it look like a problem with the tool.
Homebrew Docker CLI on macOS. brew install docker provides the CLI but not the credential helpers, which come with Docker Desktop.
Fix 1: Remove the helper
The quickest fix, and a security tradeoff worth understanding.
Edit it and delete the credsStore line:
Then log in again:
Docker now writes the credential into config.json itself:
That auth value is base64, not encryption. Anyone who can read the file has your token:
Acceptable on a personal machine or a short-lived CI runner. Not acceptable on a shared host. chmod 600 ~/.docker/config.json at minimum.
cp ~/.docker/config.json ~/.docker/config.json.bak
Fix 2: Install a helper that suits the machine
On Linux, where a desktop keyring exists:
On a headless server, secretservice needs a running D-Bus session and will not work. pass is the usual alternative:
On macOS without Docker Desktop:
sudo apt-get install -y golang-docker-credential-helpers
In CI: do not carry a config
The right answer in a pipeline is to log in during the job rather than shipping a config file.
If you must write a config, write one without credsStore:
Better still, use credHelpers to scope a helper to one registry, so a missing helper cannot break everything:
credHelpers is per-registry; credsStore is the global default. Per-registry is the safer shape, because a machine without the ECR helper still works for every other registry.
# GitHub Actions
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}The Kubernetes variant
A kubectl create secret docker-registry built from a config.json containing credsStore produces a Secret with no actual credential, since the real secret lives in the keychain. Pulls then fail with ErrImagePull and an authentication error, which is a confusing way to discover this.
Always build the Secret from explicit values:
kubectl create secret docker-registry ghcr-creds \ --docker-server=ghcr.io \ --docker-username=myuser \ --docker-password="$GITHUB_TOKEN"
A checklist
Frequently Asked Questions
What is credsStore in the Docker config?
It names an external credential helper that Docker delegates credential storage to, rather than keeping the secret itself. The value is a suffix: credsStore: "desktop" makes Docker execute docker-credential-desktop, which must be on PATH. Helpers exist so registry tokens can live in the operating system keychain instead of a plain file. When the named binary is absent, Docker fails every registry operation immediately, before any network activity, which is why the error appears even for a public image.
Is it safe to just delete the credsStore line?
It works, and it downgrades your credential storage. Without a helper Docker writes the username and token into ~/.docker/config.json as base64, which is encoding rather than encryption: anyone who can read the file can decode it with a single command. That is a reasonable tradeoff on a personal laptop or an ephemeral CI runner, and a poor one on a shared build host. At a minimum run chmod 600 ~/.docker/config.json, and prefer installing a suitable helper on any machine other people can access.
Why does minikube or Skaffold hit this when docker works fine?
Because those tools read ~/.docker/config.json directly to obtain registry credentials, and they resolve the helper themselves. If your shell has the helper on PATH but the tool runs with a different environment, or the helper is genuinely gone and docker happens to be using cached credentials, the tool fails while docker appears healthy. It is the same root cause, surfaced by a different consumer of the same file, which is why fixing the config fixes all of them at once.
How should I handle registry credentials in CI?
Log in as a step inside the job, using the platform's official login action or a docker login with the token on stdin, and never commit or bake a config.json. A committed config either leaks a credential or, more often, references a helper the runner does not have. Where a config must be written, generate it in the job without credsStore and chmod 600 it. For cloud registries, per-registry credHelpers such as ecr-login are better than a global setting, since one missing helper then cannot break every other registry.
Why does my Kubernetes image pull secret not work after creating it from my Docker config?
Because if that config uses a credential helper, it contains no actual credential; the secret is in your operating system keychain and the file only holds a pointer. Creating a Secret from it produces one with empty auth data, and the kubelet then pulls anonymously and fails. Build the Secret from explicit values instead, with kubectl create secret docker-registry --docker-server --docker-username --docker-password, which puts the real credential into the Secret where the kubelet can use it.
Reference and practice
Learn the underlying concept
Other Docker errors
Free, comprehensive DevOps tutorials and learning roadmaps. Master Docker, Kubernetes, CI/CD, and more.
Get notified about new tutorials and features.
• Roadmaps
• Interview Prep
• Certifications
• Company
© 2026 DevOpsLesson. All rights reserved.
Need to practice this scenario?
Simulate this error condition and practice recovery commands safely in our in-browser terminal.