{"record":{"id":"a1dfa5f09ae3cb97","repo":"cloudflare/cloudflared","slug":"failed-to-acquire-app-token-lock","errorCode":null,"errorMessage":"failed to acquire app token lock","messagePattern":"failed to acquire app token lock","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"token/token.go","lineNumber":348,"sourceCode":"// it appends the host of the appURL as the redirect URL to the access cli request if opening the browser\nfunc FetchToken(appURL *url.URL, appInfo *AppInfo, autoClose bool, isFedramp bool, log *zerolog.Logger) (string, error) {\n\treturn getToken(appURL, appInfo, true, autoClose, isFedramp, log)\n}\n\n// getToken will either load a stored token or generate a new one\nfunc getToken(appURL *url.URL, appInfo *AppInfo, useHostOnly bool, autoClose bool, isFedramp bool, log *zerolog.Logger) (string, error) {\n\tif token, err := GetAppTokenIfExists(appInfo); token != \"\" && err == nil {\n\t\treturn token, nil\n\t}\n\n\tappTokenPath, err := GenerateAppTokenFilePathFromURL(appInfo.AppHostname, appInfo.AppAUD, keyName)\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"failed to generate app token file path\")\n\t}\n\n\tappTokenLock, err := acquireLockFile(appTokenPath, log)\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"failed to acquire app token lock\")\n\t}\n\tdefer appTokenLock.release()\n\n\t// check to see if another process has gotten a token while we waited for the lock\n\tif token, err := GetAppTokenIfExists(appInfo); token != \"\" && err == nil {\n\t\treturn token, nil\n\t}\n\n\t// If an app token couldn't be found on disk, check for an org token and attempt to exchange it for an app token.\n\tvar orgTokenPath string\n\torgToken, orgTokenErr := GetOrgTokenIfExists(appInfo.AuthDomain)\n\tif orgTokenErr != nil {\n\t\torgTokenPath, err = generateOrgTokenFilePathFromURL(appInfo.AuthDomain)\n\t\tif err != nil {\n\t\t\treturn \"\", errors.Wrap(err, \"failed to generate org token file path\")\n\t\t}\n\n\t\torgTokenLock, orgLockErr := acquireLockFile(orgTokenPath, log)","sourceCodeStart":330,"sourceCodeEnd":366,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/token/token.go#L330-L366","documentation":"getToken wraps this error when acquireLockFile cannot secure the app-token lock file for reasons other than benign contention (mirrors the lock-creation failure path). The lock serializes concurrent token fetches for the same app across processes; without it, concurrent processes could write conflicting token files.","triggerScenarios":"FetchToken / FetchTokenWithRedirect -> getToken -> acquireLockFile(appTokenPath) returning a non-EEXIST error: unwritable token directory, stale permissions, disk full, or path issues — i.e. the lock file cannot be created at all.","commonSituations":"~/.cloudflased (sic) or ~/.cloudflared owned by root after a sudo run; running the service under a different user (systemd User=) that cannot write the token dir; container with read-only home; SELinux/AppArmor denials.","solutions":["Fix ownership/permissions of the token directory: mkdir -p ~/.cloudflared && sudo chown -R $USER ~/.cloudflared","Run cloudflared as the same user consistently (avoid mixing sudo and non-sudo runs)","Check disk space and filesystem writability for the user's home","Inspect the wrapped underlying error for the exact errno and resolve it"],"exampleFix":"// shell: repair a root-owned token directory\nsudo chown -R $(id -u):$(id -g) ~/.cloudflared\nchmod 700 ~/.cloudflared","handlingStrategy":"validation","validationCode":"// ensure the lock directory is writable by the effective user\nimport \"golang.org/x/sys/unix\"\nif err := unix.Access(homeDir+\"/.cloudflared\", unix.W_OK); err != nil {\n\treturn fmt.Errorf(\"token dir not writable: %v — run: sudo chown -R $USER ~/.cloudflared\", err)\n}","typeGuard":null,"tryCatchPattern":"token, err := FetchToken(...)\nif err != nil && strings.Contains(err.Error(), \"failed to acquire app token lock\") {\n\t// permission/environment problem; surface remediation hint\n\treturn fmt.Errorf(\"%w (hint: chown ~/.cloudflared to the running user)\", err)\n}","preventionTips":["Run cloudflared as one consistent user (pin User= in systemd)","Repair ownership after any sudo invocation","Check SELinux/AppArmor policies for the token directory","Watch disk-full conditions that break O_EXCL creation"],"tags":["filesystem","file-lock","permissions","token"],"backgroundTag":"file-write-permission-denied","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}