{"record":{"id":"20b6327d206b5f13","repo":"JanDeDobbeleer/oh-my-posh","slug":"authentication-error-s-s","errorCode":null,"errorMessage":"authentication error: %s - %s","messagePattern":"authentication error: (.+?) - (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/auth/tui/copilot.go","lineNumber":161,"sourceCode":"\t\t}\n\n\t\tif result.AccessToken != \"\" {\n\t\t\treturn result.AccessToken, nil\n\t\t}\n\n\t\tswitch result.Error {\n\t\tcase \"authorization_pending\":\n\t\t\tcontinue\n\t\tcase \"slow_down\":\n\t\t\tinterval += 5\n\t\t\tcontinue\n\t\tcase \"expired_token\":\n\t\t\treturn \"\", fmt.Errorf(\"device code expired, please try again\")\n\t\tcase \"access_denied\":\n\t\t\treturn \"\", fmt.Errorf(\"access was denied by the user\")\n\t\tdefault:\n\t\t\tif result.Error != \"\" {\n\t\t\t\treturn \"\", fmt.Errorf(\"authentication error: %s - %s\", result.Error, result.ErrorDescription)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (c *CopilotAuth) status(err error) string {\n\tif err == nil {\n\t\treturn \"Successfully authenticated with GitHub Copilot\"\n\t}\n\n\thttpErr, ok := err.(*http.Error)\n\tif !ok {\n\t\treturn err.Error()\n\t}\n\n\treturn fmt.Sprintf(\"HTTP error %d: %s\", httpErr.StatusCode, httpErr.Error())\n}\n","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/JanDeDobbeleer/oh-my-posh/blob/0976794618c5ed95de0985dded50de1b4dc914cb/src/cli/auth/tui/copilot.go#L143-L179","documentation":"During GitHub Copilot device-flow authentication, pollForToken polls GitHub's token endpoint until the user approves. When GitHub returns an OAuth error code that is not one of the expected transient states (authorization_pending, slow_down, expired_token, access_denied), the loop aborts and wraps the raw error code and description: \"authentication error: %s - %s\". It signals the device flow failed server-side for a reason the client did not specifically anticipate.","triggerScenarios":"Calling Authenticate (e.g. `oh-my-posh auth login copilot`-style flow) and GitHub's /login/oauth/access_token responds with an unrecognized error field such as \"unsupported_grant_type\", \"invalid_client\", \"invalid_grant\", or \"unauthorized_client\" instead of an access token.","commonSituations":"GitHub changing or rejecting the client_id/device-code grant (outdated oh-my-posh build), enterprise/proxy endpoints responding with policy errors, malformed device_code reuse after expiry endpoints differ, or a corporate MITM proxy returning a non-standard OAuth error payload.","solutions":["Read the error code and description echoed in the message and act on it (e.g. invalid_client -> update oh-my-posh so the bundled client_id is current)","Re-run the authentication from scratch to obtain a fresh device code","Check for network intermediaries (corporate proxy, SSL inspection) altering GitHub OAuth responses","Update oh-my-posh to the latest version and retry; if it persists, report the exact code/description upstream"],"exampleFix":"// before\nreturn \"\", fmt.Errorf(\"authentication error: %s - %s\", result.Error, result.ErrorDescription)\n\n// after (user side: retry the flow with a fresh device code)\n// oh-my-posh auth ...   # start over; the old device code is unusable","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"// Go: inspect the OAuth error code echoed in the message\nfunc oauthErrorCode(err error) string {\n\tvar parts []string\n\tif err != nil && strings.HasPrefix(err.Error(), \"authentication error: \") {\n\t\tparts = strings.SplitN(strings.TrimPrefix(err.Error(), \"authentication error: \"), \" - \", 2)\n\t}\n\tif len(parts) > 0 {\n\t\treturn parts[0]\n\t}\n\treturn \"\"\n}","tryCatchPattern":"token, err := copilotAuth.Authenticate()\nif err != nil {\n\tif strings.Contains(err.Error(), \"authentication error:\") {\n\t\t// surface the raw code/description, do not retry blindly\n\t\tlog.Printf(\"device flow rejected: %v\", err)\n\t\treturn err\n\t}\n\treturn err\n}","preventionTips":["Always start a fresh device-flow session instead of reusing an old device code","Keep oh-my-posh updated so the bundled GitHub client_id stays valid","Test authentication from a network without TLS-intercepting proxies first","Log the full error code and description before retrying"],"tags":["authentication","oauth","device-flow","network","github-copilot"],"backgroundTag":"oauth-device-flow-error","analyzedSha":"0976794618c5ed95de0985dded50de1b4dc914cb","analyzedAt":"2026-08-31T23:41:19.708Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}