{"record":{"id":"cd42a722e171d712","repo":"SonarSource/sonarqube","slug":"your-gitlab-token-was-revoked","errorCode":null,"errorMessage":"Your GitLab token was revoked","messagePattern":"Your GitLab token was revoked","errorType":"exception","errorClass":"GitlabServerException","httpStatus":null,"severity":"critical","filePath":"server/sonar-alm-client/src/main/java/org/sonar/alm/client/gitlab/GitlabApplicationClient.java","lineNumber":212,"sourceCode":"\n  private static String urlEncode(String value) {\n    try {\n      return URLEncoder.encode(value, UTF_8.toString());\n    } catch (UnsupportedEncodingException ex) {\n      throw new IllegalStateException(ex.getCause());\n    }\n  }\n\n  protected static void checkResponseIsSuccessful(Response response) throws IOException {\n    checkResponseIsSuccessful(response, \"GitLab Merge Request did not happen, please check your configuration\");\n  }\n\n  protected static void checkResponseIsSuccessful(Response response, String errorMessage) throws IOException {\n    if (!response.isSuccessful()) {\n      String body = response.body().string();\n      LOG.error(\"Gitlab API call to [{}] failed with {} http code. gitlab response content : [{}]\", response.request().url(), response.code(), body);\n      if (isTokenRevoked(response, body)) {\n        throw new GitlabServerException(response.code(), \"Your GitLab token was revoked\");\n      } else if (isTokenExpired(response, body)) {\n        throw new GitlabServerException(response.code(), \"Your GitLab token is expired\");\n      } else if (isInsufficientScope(response, body)) {\n        throw new GitlabServerException(response.code(), \"Your GitLab token has insufficient scope\");\n      } else if (response.code() == HTTP_FORBIDDEN) {\n        throw new GitlabServerException(response.code(), \"Forbidden access to GitLab. Verify your token's permissions and IP restrictions.\");\n      } else if (response.code() == HTTP_TOO_MANY_REQUESTS) {\n        throw new GitlabServerException(response.code(), \"GitLab API rate limit exceeded. Try again later.\");\n      } else if (response.code() == HTTP_UNAUTHORIZED) {\n        throw new GitlabServerException(response.code(), \"Invalid personal access token\");\n      } else if (response.isRedirect()) {\n        throw new GitlabServerException(response.code(), \"Request was redirected, please provide the correct URL\");\n      } else {\n        throw new GitlabServerException(response.code(), errorMessage);\n      }\n    }\n  }\n","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-alm-client/src/main/java/org/sonar/alm/client/gitlab/GitlabApplicationClient.java#L194-L230","documentation":"checkResponseIsSuccessful inspects every failing GitLab API response. When GitLab answers HTTP 401 and the body indicates the token was revoked, it throws GitlabServerException 'Your GitLab token was revoked'. This means the personal access token used for the GitLab DevOps integration is no longer valid and must be replaced.","triggerScenarios":"Any GitLab API call routed through checkResponseIsSuccessful (checkProjectAccess, checkToken, getPersonalAccessTokenInfo, checkWritePermission, createProjectAccessToken) receives 401 with a body matching the revoked-token signature (\"401 unauthorized\" / revoked message) at GitlabApplicationClient.java:212.","commonSituations":"A GitLab admin revoked or deleted the PAT; the user manually revoked the token in GitLab user settings; the token was invalidated by rotating it; the token was deleted after offboarding the user.","solutions":["Create a new GitLab personal access token with the required scopes (api, read_user) in GitLab > User Settings > Access Tokens.","Update the token in SonarQube under Administration > General Settings > DevOps Platform Integrations > GitLab (or re-run the binding configuration).","If the token is provided per-project, update it in the project's ALM binding settings.","Check GitLab admin audit logs to confirm who/what revoked the token before re-issuing."],"exampleFix":"// before\nString token = \"glpat-REVOKED-TOKEN\";\n// after: generate a fresh token in GitLab and store it\nString token = newGitLabPatWithApiAndReadUserScopes();","handlingStrategy":"try-catch","validationCode":"// Before configuring, check the token is alive\nResponse r = call(\"GET\", gitlabUrl + \"/api/v4/personal_access_tokens/self\", token);\nif (r.code() == 401) throw new IllegalStateException(\"GitLab token invalid or revoked — issue a new PAT with api and read_user scopes\");","typeGuard":null,"tryCatchPattern":"try {\n  gitlabClient.checkToken();\n} catch (GitlabServerException e) {\n  if (\"Your GitLab token was revoked\".equals(e.getMessage())) {\n    // prompt for a new PAT and re-run binding\n  } else { throw e; }\n}","preventionTips":["Rotate PATs proactively and update SonarQube when GitLab tokens are revoked.","Use a dedicated service-account token not tied to individuals who may leave.","Monitor GitLab audit logs for token revocation events."],"tags":["gitlab","authentication","token","http-401"],"backgroundTag":"authentication-required","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}