Repository navigation
MCP Toolkit backend stalls for hours in a Keychain call with no deadline (SecItemCopyMatching), Docker Desktop 4.94.0 on macOS 26.6.2 #732
Description
Bug report
Bug description
On Docker Desktop 4.94.0 (macOS 26.6.2, MCP Toolkit v0.44.1) the MCP Toolkit stops answering for hours while the engine stays healthy. docker version works; docker mcp oauth ls and every docker mcp gateway time out with Get "http://localhost/apps": context deadline exceeded. It happened on seven days out of eight (2026-09-30 to 2026-10-08), once clearing by itself. The menu's Restart only restarts the engine VM, so it never clears it. Sending SIGQUIT to com.docker.backend services (which writes a goroutine dump to the monitor log) and reopening Docker clears it every time. It was happening again at 17:28 ET on 2026-10-08 (backend up 12 h 16 min).
Expected: the toolkit keeps answering, or a stuck Keychain read times out and fails only that one request.
Reproduction steps
We cannot trigger it on demand. It has recurred about once a day on a Mac with four authorized OAuth providers and several MCP clients that each start their own docker mcp gateway run (about twenty such processes were running during the measurement below; we have not proven that is required). Once it is wedged, docker mcp oauth ls fails at its 10 s deadline while docker version answers at once.
Evidence 1: a Keychain call with no deadline, held under a lock
The goroutine dump from 2026-10-06 (284 goroutines) shows two goroutines inside SecItemCopyMatching for 673 minutes, and 106 goroutines blocked on mutexes behind them (the longest 673 minutes; 67 of them in docker-credential-desktop.(*cache).List). One stuck stack, trimmed to function names and build paths:
runtime.cgocall
github.com/docker/secrets-engine/store/keychain/internal/go-keychain._Cfunc_SecItemCopyMatching
github.com/docker/secrets-engine/store/keychain/internal/go-keychain.QueryItemRef (go-keychain/keychain.go:526)
github.com/docker/secrets-engine/store/keychain/internal/go-keychain.QueryItem (go-keychain/keychain.go:539)
github.com/docker/secrets-engine/store/keychain.getItemWithData[...] (keychain_darwin.go:93)
github.com/docker/secrets-engine/store/keychain.(*keychainStore[...]).loadSecret (keychain_darwin.go:291)
github.com/docker/secrets-engine/store/keychain.(*keychainStore[...]).Filter (keychain_darwin.go:278, 225)
github.com/docker/pinata/common/cmd/com.docker.backend/internal/store.(*service).Filter
github.com/docker/pinata/common/cmd/com.docker.backend/internal/oauthmanager/store.(*transformerStore).Filter
github.com/docker/pinata/common/cmd/com.docker.backend/internal/server.(*desktopPlugin).GetSecrets
github.com/docker/secrets-engine-private/runtime/internal/secrets/builtin.(*builtinProvider).GetSecrets
The same call was stuck in a second dump on 2026-10-08. Everything else in the backend stayed alive (engine proxy, vfkit, the periodic docker-credential-osxkeychain list polling), which is why docker version works while the toolkit's /apps API does not. Ask: put a deadline on every Keychain call, and do not hold the cache mutexes across it.
New measurement from a live jam (2026-10-08, 17:28 ET)
While the toolkit was jammed (backend process up 12 h 16 min, state S, about 7% CPU), two NEW processes used the same login keychain without trouble: docker-credential-osxkeychain list returned in 0.02 s and security show-keychain-info on the login keychain in 0.01 s (security show-keychain-info reports no-timeout). In the same minute docker mcp oauth ls hit its 10 s deadline. In the backend log's current segment (18 minutes) three GET /apps requests from the toolkit's API arrived and none was answered; no response line was written for any request on that API. So the Keychain service is answering and the stall is specific to the backend process. This does not show why the call stops returning.
Evidence 2: token refresh window (a separate, smaller defect)
Docker's proxy log shows 11 failing connections to a remote MCP server on three separate days, every one inside the last ~4.5 minutes before the stored OAuth token expires (the client answers Unauthorized at initialize, then client is closing, while docker mcp oauth ls still says authorized). A clean read follows a few minutes later. Forty startups inside such windows were clean, so it is intermittent. Separately, on 2026-10-08 the refresh woke 0.34 s before Docker's own 10 s threshold, did nothing, and tried again 30 s later, leaving the stored token hard-expired for about 20 s. A log line token refresh succeeded appeared on a no-op re-save, so it proves only that a pass finished. We have NOT proven the mechanism and are not claiming the refresh lacks single-flight (the proxy log shows one token exchange in the burst we first suspected).
What we ruled out
Display sleep and screen lock; keychain auto-lock (the login keychain reads no-timeout and unlocked, 15 ms reads); the Mac sleeping (held awake); a download or downgrade (4.94.0 is the newest release and wedges were seen on 4.76 and 4.78). A load of 14 dead OAuth providers was removed after the first jam and the jams continued with four live providers.
What we do not know
Why SecItemCopyMatching stops answering inside the backend. secd logs say Docker's helper binaries are treated as having an "invalid application signature or incorrect provisioning profile" (entitlement group.com.docker ignored; -34018 for docker-credential-*), but codesign --verify on the app passes and no SecurityAgent prompt was open. The new measurement says the fault is per-process rather than system-wide; we have not found what the stuck call is waiting on.
Offer
We can attach the full goroutine dumps (paths and account names removed) and a timeline of the seven episodes if useful.
Related
- Hardening: Secrets Engine does not get jammed when plugins take forever to return secrets secrets-engine#113: hardening so the Secrets Engine does not jam when plugins never return secrets
- consider a timeout when calling docker-credential-osxkeychain docker-credential-helpers#355: consider a timeout when calling docker-credential-osxkeychain
- startup hangs indefinitely when docker-credential-desktop wedges docker-agent#2972 (closed): startup hangs indefinitely when docker-credential-desktop wedges
Platform
macOS
Version information
Docker Desktop 4.94.0 (newest release at the time of writing)
Docker Engine 29.8.2
Docker MCP Toolkit v0.44.1
macOS 26.6.2Diagnostics ID
No response
Activity