{"record":{"id":"436adaee63e40ed9","repo":"SonarSource/sonarqube","slug":"failed-to-create-github-s-user-access-token-githu","errorCode":null,"errorMessage":"Failed to create GitHub's user access token. GitHub returned code ","messagePattern":"Failed to create GitHub's user access token\\. GitHub returned code ","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"server/sonar-alm-client/src/main/java/org/sonar/alm/client/github/GithubApplicationClientImpl.java","lineNumber":385,"sourceCode":"      throw new IllegalStateException(format(\"Failed to get repository '%s' on '%s' (this might be related to the GitHub App installation scope)\",\n        organizationAndRepository, appUrl), e);\n    }\n  }\n\n  @Override\n  public UserAccessToken createUserAccessToken(String appUrl, String clientId, String clientSecret, String code) {\n    try {\n      String endpoint = \"/login/oauth/access_token?client_id=\" + clientId + \"&client_secret=\" + clientSecret + \"&code=\" + code;\n\n      String baseAppUrl = convertApiUrlToBaseUrl(appUrl);\n\n      ApplicationHttpClient.Response response = githubApplicationHttpClient.post(baseAppUrl, null, endpoint);\n\n      if (response.getCode() != HTTP_OK) {\n        if (LOG.isDebugEnabled()) {\n          LOG.debug(\"Failed to create GitHub's user access token, response body: {}\", response.getContent().orElse(\"\"));\n        }\n        throw new IllegalStateException(\"Failed to create GitHub's user access token. GitHub returned code \" + response.getCode() + \".\");\n      }\n\n      Optional<String> content = response.getContent();\n      Optional<UserAccessToken> accessToken = content.flatMap(c -> Arrays.stream(c.split(\"&\"))\n          .filter(t -> t.startsWith(\"access_token=\"))\n          .map(t -> t.split(\"=\")[1])\n          .findAny())\n        .map(UserAccessToken::new);\n\n      if (accessToken.isPresent()) {\n        return accessToken.get();\n      }\n\n      // If token is not in the 200's body, it's because the client ID or client secret are incorrect\n      LOG.error(\"Failed to create GitHub's user access token. GitHub's response: {}\", content);\n      throw new IllegalArgumentException();\n    } catch (IOException e) {\n      throw new IllegalStateException(\"Failed to create GitHub's user access token\", e);","sourceCodeStart":367,"sourceCodeEnd":403,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-alm-client/src/main/java/org/sonar/alm/client/github/GithubApplicationClientImpl.java#L367-L403","documentation":"createUserAccessToken exchanges an OAuth code for a user access token via GitHub's login/oauth/access_token endpoint. If GitHub returns a non-200 code, the response body is logged at DEBUG and this IllegalStateException is thrown including the returned code. It indicates the token exchange HTTP call itself failed rather than an application-level rejection.","triggerScenarios":"Calling createUserAccessToken(appUrl, clientId, clientSecret, code) when the POST response code != 200 — e.g. 404 from wrong appUrl, 5xx from GitHub, or 5xx/4xx at transport level.","commonSituations":"GitHub Enterprise URL misconfigured (endpoint path wrong), network outage, clientId/clientSecret pair invalid for that GitHub instance causing unexpected status handling differences.","solutions":["Enable DEBUG logging for org.sonar.alm.client to see the response body details.","Verify the appUrl points to the correct GitHub instance root (api base used to build the endpoint).","Confirm network connectivity from the SonarQube server to the GitHub host.","Retry the authorization flow to obtain a fresh code; if the code was the issue, error 45/400-family messaging typically applies instead."],"exampleFix":"// before\nclient.createUserAccessToken(\"https://ghe.example.com/bad\", clientId, secret, code);\n// after\nclient.createUserAccessToken(\"https://ghe.example.com\", clientId, secret, code);","handlingStrategy":"try-catch","validationCode":"// preflight\nif (!appUrl.startsWith(\"https://\")) throw new IllegalArgumentException(\"appUrl must be https\");\nif (clientId == null || clientId.isBlank() || clientSecret == null || clientSecret.isBlank()) throw new IllegalArgumentException(\"Missing OAuth credentials\");","typeGuard":null,"tryCatchPattern":"try { client.createUserAccessToken(url, clientId, secret, code); } catch (IllegalStateException e) { log.error(\"Token exchange HTTP failure (see DEBUG body log)\", e); throw e; }","preventionTips":["Enable DEBUG logging for org.sonar.alm.client during setup","Validate the GHES URL with a simple GET before OAuth flows","Ensure the OAuth App callback URL matches the configured endpoint","Use fresh codes; exchange immediately after user consent"],"tags":["github","oauth","http","alm-binding"],"backgroundTag":"oauth-token-exchange-failed","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"}