{"record":{"id":"db4544e07f693689","repo":"oauth2-proxy/oauth2-proxy","slug":"failed-to-retrieve-user-info-v","errorCode":null,"errorMessage":"failed to retrieve user info: %v","messagePattern":"failed to retrieve user info: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"providers/gitlab.go","lineNumber":128,"sourceCode":"}\n\n// setProjectScope ensures read_api is added to scope when filtering on projects\nfunc (p *GitLabProvider) setProjectScope() {\n\tfor _, val := range strings.Split(p.Scope, \" \") {\n\t\tif val == \"read_api\" {\n\t\t\treturn\n\t\t}\n\t}\n\tp.Scope += \" read_api\"\n}\n\n// EnrichSession enriches the session with the response from the userinfo API\n// endpoint & projects API endpoint for allowed projects.\nfunc (p *GitLabProvider) EnrichSession(ctx context.Context, s *sessions.SessionState) error {\n\t// Retrieve user info\n\tuserinfo, err := p.getUserinfo(ctx, s)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to retrieve user info: %v\", err)\n\t}\n\n\t// Check if email is verified\n\tif !p.AllowUnverifiedEmail && !userinfo.EmailVerified {\n\t\treturn fmt.Errorf(\"user email is not verified\")\n\t}\n\n\tif userinfo.Nickname != \"\" {\n\t\ts.User = userinfo.Nickname\n\t}\n\tif userinfo.Email != \"\" {\n\t\ts.Email = userinfo.Email\n\t}\n\tif len(userinfo.Groups) > 0 {\n\t\ts.Groups = userinfo.Groups\n\t}\n\n\t// Add projects as `project:blah` to s.Groups","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/oauth2-proxy/oauth2-proxy/blob/33c2eb92dea78204f7a18bc2dfdbccc220f39257/providers/gitlab.go#L110-L146","documentation":"EnrichSession is called after the OAuth token is redeemed to add GitLab user info and allowed-projects data to the session. This error wraps any failure from p.getUserinfo, i.e. the HTTP GET to the GitLab /user endpoint (via the userinfo URL) failed or its response could not be unmarshalled. The session is rejected, so the user cannot authenticate.","triggerScenarios":"The GET to the GitLab userinfo URL fails: network/DNS failure, GitLab returning a non-2xx (401 on an expired/invalid access token, 403, 5xx), or a response body that does not unmarshal into the userinfo struct.","commonSituations":"Access token revoked or expired between redeem and enrich; self-hosted GitLab behind a misconfigured reverse proxy returning HTML error pages; network egress blocked from the proxy container; GitLab instance temporarily down.","solutions":["Read the wrapped inner error (%v) in the log — it tells you whether it was an HTTP status failure or an unmarshal problem.","Verify the access token is valid: re-run the auth flow; if it recurs per-request, check token lifetime/refresh configuration.","Test connectivity from the oauth2-proxy host: curl -H 'Authorization: Bearer <token>' https://<gitlab>/api/v4/user.","If self-hosted, confirm the gitlab endpoint/oidc URLs in config point to the correct reachable instance and that TLS is trusted.","Check the GitLab instance status (API rate limits, maintenance) if the failure is intermittent."],"exampleFix":"// before (reverse proxy returning HTML on /api/v4/user)\n# gitlab endpoint pointing at web UI proxy\ngitlab = \"https://gitlab.example.com\"\n// after\ngitlab = \"https://gitlab-api.example.com\" # direct, API-capable endpoint","handlingStrategy":"try-catch","validationCode":"resp, err := http.Get(gitlabURL + \"/api/v4/user\") // basic reachability check before configuring\nif err != nil { return fmt.Errorf(\"gitlab unreachable: %w\", err) }","typeGuard":null,"tryCatchPattern":"if err := provider.EnrichSession(ctx, session); err != nil {\n    if strings.Contains(err.Error(), \"failed to retrieve user info\") {\n        // inspect wrapped cause, optionally retry once on transient network errors\n        log.Printf(\"gitlab userinfo unavailable: %v\", err)\n        http.Error(rw, \"upstream unavailable\", http.StatusBadGateway)\n        return\n    }\n    return err\n}","preventionTips":["Monitor egress connectivity from the oauth2-proxy host to the GitLab instance","Ensure access tokens are refreshed before expiry so userinfo calls don't hit 401","Point gitlab URLs directly at the API-capable host, not an HTML-serving proxy","Add health checks/alerts on the GitLab instance"],"tags":["gitlab","network","http","userinfo","oauth2-proxy"],"backgroundTag":"api-request-failed","analyzedSha":"33c2eb92dea78204f7a18bc2dfdbccc220f39257","analyzedAt":"2026-09-06T08:51:53.077Z","contentChangedAt":"2026-09-06T08:51:53.077Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}