{"record":{"id":"1d552bfbe640fe09","repo":"SonarSource/sonarqube","slug":"fail-to-execute-request-s-http-code-s-respo","errorCode":null,"errorMessage":"Fail to execute request '%s'. HTTP code: %s, response: %s","messagePattern":"Fail to execute request '(.+?)'\\. HTTP code: (.+?), response: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"server/sonar-auth-common/src/main/java/org/sonar/auth/OAuthRestClient.java","lineNumber":54,"sourceCode":"\nimport static java.lang.String.format;\n\npublic class OAuthRestClient {\n\n  private static final int DEFAULT_PAGE_SIZE = 100;\n  private static final Pattern NEXT_LINK_PATTERN = Pattern.compile(\"<([^<]+)>; rel=\\\"next\\\"\");\n\n  private OAuthRestClient() {\n    // Only static method\n  }\n\n  public static Response executeRequest(String requestUrl, OAuth20Service scribe, OAuth2AccessToken accessToken) throws IOException {\n    OAuthRequest request = new OAuthRequest(Verb.GET, requestUrl);\n    scribe.signRequest(accessToken, request);\n    try {\n      Response response = scribe.execute(request);\n      if (!response.isSuccessful()) {\n        throw unexpectedResponseCode(requestUrl, response);\n      }\n      return response;\n    } catch (InterruptedException e) {\n      Thread.currentThread().interrupt();\n      throw new IllegalStateException(e);\n    } catch (ExecutionException e) {\n      throw new IllegalStateException(e);\n    }\n  }\n\n  public static <E> List<E> executePaginatedRequest(String request, OAuth20Service scribe, OAuth2AccessToken accessToken, Function<String, List<E>> function) {\n    List<E> result = new ArrayList<>();\n    readPage(result, scribe, accessToken, addPerPageQueryParameter(request, DEFAULT_PAGE_SIZE), function);\n    return result;\n  }\n\n  public static String addPerPageQueryParameter(String request, int pageSize) {\n    String separator = request.contains(\"?\") ? \"&\" : \"?\";","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-auth-common/src/main/java/org/sonar/auth/OAuthRestClient.java#L36-L72","documentation":"OAuthRestClient.executeRequest performs a signed GET against an external identity-provider API (e.g. GitHub/GitLab/Bitbucket) using ScribeJava. If the HTTP response status is not 2xx, SonarQube aborts and throws this message embedding the URL, status code, and response body. It indicates the upstream ALM API rejected the request — bad/expired token, wrong URL, or provider-side error.","triggerScenarios":"Calling readPage (pagination fetch of users/groups from the ALM) when the provider returns 401/403/404/5xx: expired or revoked OAuth access token, insufficient token scopes, wrong API base URL configured, or the provider being temporarily down (502/503).","commonSituations":"DevOps rotated GitHub App credentials or revoked tokens; ALM base URL points to an on-prem instance with a different API path; token scopes narrowed (missing repo/read:org); corporate proxy returning 403; rate limiting from the provider.","solutions":["Check the URL, status code and body in the message to identify the provider-side cause.","Regenerate/re-authorize the OAuth app or token in SonarQube ALM settings (Administration > DevOps Platform) if the response is 401/403.","Verify the ALM base URL and that the account has the required scopes (e.g. GitHub: repo, read:org).","Check provider status/rate limits for 429/5xx and retry after the issue clears.","Confirm network/proxy configuration allows SonarQube to reach the provider."],"exampleFix":"// before\nsettings.put(\"alm.github.url\", \"https://github.example.internal/api\"); // wrong API path\n// after\nsettings.put(\"alm.github.url\", \"https://github.example.internal\"); // correct base URL + re-authorized token","handlingStrategy":"retry","validationCode":"// Java: check token and URL before calling\nif (accessToken == null || accessToken.getAccessToken().isEmpty()) throw new IllegalArgumentException(\"missing access token\");\nif (!requestUrl.startsWith(\"https://\")) throw new IllegalArgumentException(\"ALM URL must be https\");","typeGuard":"boolean isUsableToken(OAuth2AccessToken t) { return t != null && t.getAccessToken() != null && !t.getAccessToken().isEmpty(); }","tryCatchPattern":"try {\n  Response r = OAuthRestClient.executeRequest(url, scribe, token);\n} catch (IOException e) {\n  if (e.getMessage().contains(\"HTTP code: 40\") ) refreshTokenAndRetry();\n  else if (e.getMessage().contains(\"HTTP code: 429\") || e.getMessage().contains(\"HTTP code: 5\")) backoffAndRetry();\n  else throw new AlmConfigurationException(e);\n}","preventionTips":["Re-authorize ALM connections whenever credentials or scopes change","Monitor provider status pages and rate limits","Log the full response body for diagnosis (it is embedded in the message)","Validate ALM base URLs right after configuration changes"],"tags":["oauth","http","network","external-api","sonarqube"],"backgroundTag":"http-error-response","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"}