{"record":{"id":"e13283c6936189e0","repo":"cloudflare/cloudflared","slug":"failed-to-get-app-info","errorCode":null,"errorMessage":"failed to get app info","messagePattern":"failed to get app info","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"token/token.go","lineNumber":496,"sourceCode":"// followed.\nfunc fetchMetadataJWT(reqURL string) (string, error) {\n\tclient := &http.Client{\n\t\tCheckRedirect: func(_ *http.Request, _ []*http.Request) error {\n\t\t\treturn http.ErrUseLastResponse\n\t\t},\n\t\tTimeout: time.Second * 7,\n\t}\n\n\treq, err := http.NewRequest(\"HEAD\", reqURL, nil)\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"failed to create app info request\")\n\t}\n\treq.Header.Set(accessMetadataReqHeader, accessMetadataReqValue)\n\treq.Header.Set(userAgentHeader, userAgent)\n\n\tresp, err := client.Do(req) // nolint: gosec\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"failed to get app info\")\n\t}\n\t_ = resp.Body.Close()\n\n\trawJWT := resp.Header.Get(accessMetadataRespHeader)\n\tif rawJWT == \"\" {\n\t\treturn \"\", fmt.Errorf(\"failed to find Access application at %s\", reqURL)\n\t}\n\treturn rawJWT, nil\n}\n\nfunc validateMetadataIssuedAt(iat int64, now time.Time) error {\n\tif iat <= 0 {\n\t\treturn errors.New(\"metadata JWT iat is missing or invalid\")\n\t}\n\tissuedAt := time.Unix(iat, 0)\n\tif issuedAt.Before(now.Add(-metadataMaxAge)) {\n\t\treturn fmt.Errorf(\"metadata JWT is older than %s\", metadataMaxAge)\n\t}","sourceCodeStart":478,"sourceCodeEnd":514,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/token/token.go#L478-L514","documentation":"This error wraps a client.Do failure when issuing the HEAD request that fetches the Access application metadata JWT (via the Cf-Access-Jwt-Assertion style header) from the target URL. It is thrown when the HTTP round trip itself fails — DNS resolution, TCP connect, TLS handshake, or timeout (the client has a 7-second timeout). It is a transport-level error, not an HTTP status problem.","triggerScenarios":"fetchMetadataJWT (via GetAppInfo) calls client.Do(req) and receives a non-nil err: host unreachable, DNS failure, connection refused, TLS error, or the 7-second timeout elapses.","commonSituations":"Target host is behind a firewall or offline; no network connectivity; private/internal hostname not resolvable from the machine; TLS interception proxies breaking the handshake; server slow to respond causing the 7s timeout.","solutions":["Verify the target URL is reachable: curl -I <url> from the same machine","Check DNS resolution (nslookup/dig) for the hostname","Confirm network/firewall/proxy settings allow outbound HTTPS to the host","Investigate intermittent slowness if the wrapped error is a timeout — the client uses a 7-second timeout","Retry the operation if the failure was transient (network blip)"],"exampleFix":"// before: no reachability check\njwt, err := fetchMetadataJWT(ctx, reqURL, log)\n// after: probe connectivity first\nresp, err := http.Head(reqURL)\nif err != nil {\n\treturn fmt.Errorf(\"app at %s is unreachable, check network/DNS: %w\", reqURL, err)\n}\nresp.Body.Close()\njwt, err = fetchMetadataJWT(ctx, reqURL, log)","handlingStrategy":"retry","validationCode":"conn, err := net.DialTimeout(\"tcp\", host+\":443\", 3*time.Second)\nif err != nil {\n\treturn fmt.Errorf(\"app host unreachable before metadata fetch: %w\", err)\n}\nconn.Close()","typeGuard":null,"tryCatchPattern":"for attempt := 0; attempt < 3; attempt++ {\n\tjwt, err := GetAppInfo(ctx, reqURL, log)\n\tif err == nil {\n\t\tbreak\n\t}\n\tif !strings.Contains(err.Error(), \"failed to get app info\") {\n\t\treturn err\n\t}\n\ttime.Sleep(time.Duration(1<<attempt) * time.Second)\n}","preventionTips":["Pre-check DNS and TCP reachability of the Access app host","Account for the 7-second client timeout; avoid using it on slow hosts","Verify VPN/proxy settings allow egress to the target domain","Add bounded retries with backoff for transient network errors"],"tags":["network","http","timeout","dns"],"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"}