{"record":{"id":"e21a7b654653166e","repo":"SonarSource/sonarqube","slug":"request-was-redirected-please-provide-the-correct","errorCode":null,"errorMessage":"Request was redirected, please provide the correct URL","messagePattern":"Request was redirected, please provide the correct URL","errorType":"exception","errorClass":"GitlabServerException","httpStatus":null,"severity":"error","filePath":"server/sonar-alm-client/src/main/java/org/sonar/alm/client/gitlab/GitlabApplicationClient.java","lineNumber":224,"sourceCode":"\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\n  private static boolean isTokenRevoked(Response response, String body) {\n    if (response.code() == HTTP_UNAUTHORIZED) {\n      try {\n        Optional<GsonError> gitlabError = GsonError.parseOne(body);\n        return gitlabError.map(GsonError::getErrorDescription).map(description -> description.contains(\"Token was revoked\")).orElse(false);\n      } catch (JsonParseException e) {\n        // nothing to do\n      }\n    }\n    return false;\n  }\n","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-alm-client/src/main/java/org/sonar/alm/client/gitlab/GitlabApplicationClient.java#L206-L242","documentation":"If the OkHttp response is a redirect, checkResponseIsSuccessful throws GitlabServerException 'Request was redirected, please provide the correct URL'. OkHttp normally follows redirects transparently, so a visible redirect means the call landed somewhere that demanded authentication (e.g. an SSO/login page) — the configured GitLab URL is not the direct API endpoint.","triggerScenarios":"Any GitLab API call via checkResponseIsSuccessful receives a 3xx redirect response (response.isRedirect()) at GitlabApplicationClient.java:224 — typically when the base URL points at a login/SSO page or a redirecting gateway.","commonSituations":"GitLab URL configured with /users/sign_in path; http:// URL redirected to https:// by the server; SSO/IDP portal in front of GitLab redirecting unauthenticated API calls; load balancer redirecting to a different host.","solutions":["Set the GitLab URL to the instance root without login paths (e.g. https://gitlab.example.com, not https://gitlab.example.com/users/sign_in).","Use https:// directly if http:// is being redirected.","If an SSO proxy fronts GitLab, ensure API paths bypass SSO redirects or use an allow-listed route for the SonarQube server.","Check with curl -IL whether the configured URL issues a redirect before calling the API."],"exampleFix":"// before\ngitlab.url = https://gitlab.example.com/users/sign_in\n// after\ngitlab.url = https://gitlab.example.com","handlingStrategy":"validation","validationCode":"// Reject redirecting URLs before configuring the integration\nHttpURLConnection c = (HttpURLConnection) new URL(gitlabUrl + \"/api/v4/version\").openConnection();\nc.setInstanceFollowRedirects(false);\nif (c.getResponseCode() >= 300 && c.getResponseCode() < 400) {\n  throw new IllegalStateException(\"GitLab URL redirects to \" + c.getHeaderField(\"Location\") + \" — use the direct instance root URL\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Configure the GitLab instance root, never login/SSO paths.","Use the final https URL directly if http redirects to https.","Verify with curl -IL that the configured URL returns 200/401, not 3xx."],"tags":["gitlab","url","http-3xx","configuration","network"],"backgroundTag":"invalid-url","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"}