{"record":{"id":"b333b4b7f5323776","repo":"cloudflare/cloudflared","slug":"failed-to-get-app-token","errorCode":null,"errorMessage":"failed to get app token","messagePattern":"failed to get app token","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"token/token.go","lineNumber":566,"sourceCode":"\n// exchangeOrgToken attaches an org token to a request to the appURL and returns an app token. This uses the Access SSO\n// flow to automatically generate and return an app token without the login page.\nfunc exchangeOrgToken(appURL *url.URL, orgToken string) (string, error) {\n\tclient := &http.Client{\n\t\tCheckRedirect: func(req *http.Request, via []*http.Request) error {\n\t\t\treturn handleRedirects(req, via, orgToken)\n\t\t},\n\t\tTimeout: time.Second * 7,\n\t}\n\n\tappTokenRequest, err := http.NewRequest(\"HEAD\", appURL.String(), nil)\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"failed to create app token request\")\n\t}\n\tappTokenRequest.Header.Add(userAgentHeader, userAgent)\n\tresp, err := client.Do(appTokenRequest) // nolint: gosec\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"failed to get app token\")\n\t}\n\t_ = resp.Body.Close()\n\tvar appToken string\n\tfor _, c := range resp.Cookies() {\n\t\t//if Org token revoked on exchange, getTokensFromEdge instead\n\t\tvalidAppToken := c.Name == tokenCookie && time.Now().Before(c.Expires)\n\t\tif validAppToken {\n\t\t\tappToken = c.Value\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif len(appToken) > 0 {\n\t\treturn appToken, nil\n\t}\n\treturn \"\", fmt.Errorf(\"response from %s did not contain app token\", resp.Request.URL.String())\n}\n","sourceCodeStart":548,"sourceCodeEnd":584,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/token/token.go#L548-L584","documentation":"This error wraps a client.Do failure during exchangeOrgToken, when the HEAD request to the application URL (used to obtain the app-token cookie) fails at the transport level. Thrown when DNS, connection, TLS, or the 7-second timeout fails; it is distinct from an HTTP error status, which is handled afterward by scanning cookies. On this failure the caller (getToken) typically falls back to re-fetching tokens from the edge.","triggerScenarios":"exchangeOrgToken calls client.Do(appTokenRequest) and gets a transport error: app host unreachable, connection refused, TLS handshake failure, or request exceeding the 7-second client timeout.","commonSituations":"Application hostname is internal-only and unreachable from the client machine; network interruption mid-session; slow origin causing repeated timeouts; corporate proxy blocking the request.","solutions":["Check reachability of the app URL (curl -I) and DNS from the client machine","If the org token is stale, remove the cached org token and re-run cloudflared access login to get tokens from the edge directly","Retry on transient network errors; investigate proxy/VPN interference","If timeouts recur, check origin latency behind the Access application"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"conn, err := net.DialTimeout(\"tcp\", appURL.Hostname()+\":443\", 3*time.Second)\nif err != nil {\n\t// app host unreachable; fall back to getTokensFromEdge\n}\nconn.Close()","typeGuard":null,"tryCatchPattern":"for i := 0; i < 3; i++ {\n\tappToken, err := exchangeOrgToken(ctx, appURL, log)\n\tif err == nil {\n\t\tbreak\n\t}\n\tif isTimeout(err) {\n\t\ttime.Sleep(2 * time.Second)\n\t\tcontinue\n\t}\n\t// non-transient: fall back to full edge token fetch\n\tappToken, err = getTokensFromEdge(ctx, log)\n\tbreak\n}","preventionTips":["Handle the 7-second timeout explicitly in retries","Fall back to getTokensFromEdge when exchange repeatedly fails","Check connectivity to the app origin before exchanging tokens","Keep org tokens fresh; expired org tokens lead to failed exchanges"],"tags":["network","http","token","timeout"],"backgroundTag":"http-request-failed","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}