{"record":{"id":"651a2ab696a86438","repo":"docker/cli","slug":"failed-waiting-for-authentication-w","errorCode":null,"errorMessage":"failed waiting for authentication: %w","messagePattern":"failed waiting for authentication: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/oauth/manager/manager.go","lineNumber":133,"sourceCode":"\t\t\twaitForTokenErrChan <- err\n\t\t\treturn\n\t\t}\n\t\ttokenResChan <- tokenRes\n\t}()\n\n\tgo func() {\n\t\treader := bufio.NewReader(os.Stdin)\n\t\t_, _ = reader.ReadString('\\n')\n\t\t_ = m.openBrowser(state.VerificationURI)\n\t}()\n\n\t_, _ = fmt.Fprint(w, \"\\nWaiting for authentication in the browser…\\n\")\n\tvar tokenRes api.TokenResponse\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn nil, errors.New(\"login canceled\")\n\tcase err := <-waitForTokenErrChan:\n\t\treturn nil, fmt.Errorf(\"failed waiting for authentication: %w\", err)\n\tcase tokenRes = <-tokenResChan:\n\t}\n\n\tclaims, err := oauth.GetClaims(tokenRes.AccessToken)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse token claims: %w\", err)\n\t}\n\n\terr = m.storeTokensInStore(tokenRes, claims.Domain.Username)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to store tokens: %w\", err)\n\t}\n\n\tpat, err := m.api.GetAutoPAT(ctx, m.audience, tokenRes)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/internal/oauth/manager/manager.go#L115-L151","documentation":"Returned by OAuthManager.Login when the goroutine polling for the device token (m.api.WaitForDeviceToken) returns an error instead of a TokenResponse. WaitForDeviceToken loops calling getDeviceToken until the user completes browser auth; any non-nil result (network, decode, or terminal OAuth error like expired_device_code) surfaces here wrapped with %w.","triggerScenarios":"The user never completes browser authentication, the device code expires, the browser never opens (press Enter triggers m.openBrowser), network drops during polling, or the tenant returns a fatal OAuth error.","commonSituations":"Headless environments with no browser; user closes the browser tab; slow user exceeding device_code TTL; network change mid-login; redirect blocked by popup blocker.","solutions":["Re-run `docker login` and complete the browser prompt promptly.","On headless hosts, copy the printed verification URL into a browser on another machine.","Ensure network/proxy is stable for the whole polling window.","If it persists, inspect the wrapped error (e.g. expired_token) and start a fresh flow."],"exampleFix":"# before (user didn't finish, code expired)\ndocker login  # -> failed waiting for authentication: expired_token\n# after\ndocker login  # open URL quickly this time\n# headless: copy the verification URL to a browser elsewhere","handlingStrategy":"retry","validationCode":"// only start device flow when a browser is feasible\nif !canOpenBrowser() { return errors.New(\"use `docker login -u <user>` with a PAT on headless hosts\") }","typeGuard":null,"tryCatchPattern":"if errors.Is(err, context.Canceled) { /* user canceled; do not retry */ } else { /* retry the device flow */ }","preventionTips":["On headless hosts, prefer PAT login over the device flow.","Complete the browser step within the device_code TTL.","Surface the verification URL to the user immediately."],"tags":["oauth","docker-hub","device-flow","auth","browser"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}