{"record":{"id":"584a3ec0f21a7ce8","repo":"SonarSource/sonarqube","slug":"failed-to-create-the-github-app-from-manifest","errorCode":null,"errorMessage":"Failed to create the GitHub App from manifest","messagePattern":"Failed to create the GitHub App from manifest","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"server/sonar-alm-client/src/main/java/org/sonar/alm/client/github/GithubApplicationClientImpl.java","lineNumber":426,"sourceCode":"  public GithubAppCredentials convertAppManifest(String apiEndpoint, String code) {\n    String endpoint = \"/app-manifests/\" + URLEncoder.encode(code, StandardCharsets.UTF_8) + \"/conversions\";\n    try {\n      // Unauthenticated call: the GitHub App does not exist yet, so no JWT/app token is available.\n      ApplicationHttpClient.Response response = githubApplicationHttpClient.post(apiEndpoint, null, endpoint);\n\n      if (response.getCode() != HTTP_CREATED && response.getCode() != HTTP_OK) {\n        if (LOG.isDebugEnabled()) {\n          LOG.debug(\"GitHub manifest conversion failed, response body: {}\", response.getContent().orElse(\"\"));\n        }\n        throw new IllegalStateException(\n          \"Failed to create the GitHub App from manifest. GitHub returned code \" + response.getCode());\n      }\n\n      return response.getContent()\n        .map(content -> GSON.fromJson(content, GithubAppCredentials.class))\n        .orElseThrow(() -> new IllegalStateException(\"Failed to create the GitHub App from manifest, response body was empty\"));\n    } catch (IOException e) {\n      throw new IllegalStateException(\"Failed to create the GitHub App from manifest\", e);\n    }\n  }\n\n  @Override\n  public GithubBinding.GsonApp getApp(GithubAppConfiguration githubAppConfiguration) {\n    AppToken appToken = appSecurity.createAppToken(githubAppConfiguration.getId(), githubAppConfiguration.getPrivateKey());\n    String endpoint = \"/app\";\n    return getOrThrowIfNotHttpOk(githubAppConfiguration.getApiEndpoint(), appToken, endpoint, GithubBinding.GsonApp.class);\n  }\n\n  private <T> T getOrThrowIfNotHttpOk(String baseUrl, AccessToken token, String endPoint, Class<T> gsonClass) {\n    try {\n      GetResponse response = githubApplicationHttpClient.get(baseUrl, token, endPoint);\n      if (response.getCode() != HTTP_OK) {\n        throw new HttpException(baseUrl + endPoint, response.getCode(), response.getContent().orElse(\"\"));\n      }\n      return handleResponse(response, endPoint, gsonClass).orElseThrow(() -> new ServerException(HTTP_INTERNAL_ERROR, \"Http response withuot content\"));\n    } catch (IOException e) {","sourceCodeStart":408,"sourceCodeEnd":444,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-alm-client/src/main/java/org/sonar/alm/client/github/GithubApplicationClientImpl.java#L408-L444","documentation":"In convertAppManifest, an IOException during the HTTP POST to the manifest conversion endpoint is wrapped in this IllegalStateException. Unlike error 46 (bad status code), this indicates the request never completed at the transport level.","triggerScenarios":"Calling convertAppManifest(apiEndpoint, code) when the underlying HTTP client throws IOException — connection refused, timeout, TLS failure to apiEndpoint.","commonSituations":"GHES host unreachable from the SonarQube server, DNS misconfiguration, proxy blocking the POST, self-signed certificate not trusted by the JVM.","solutions":["Test connectivity from the SonarQube server to the apiEndpoint host (curl -v).","Fix DNS/proxy/firewall so the POST can reach GitHub.","Add the instance's TLS certificate to the JVM truststore if using an internal CA.","Correct the apiEndpoint value in the DevOps platform settings."],"exampleFix":"// before\nclient.convertAppManifest(\"https://ghe-wrong-host.example.com\", code);\n// after\nclient.convertAppManifest(\"https://ghe.example.com/api/v3\", code);","handlingStrategy":"retry","validationCode":"// preflight reachability of the conversion endpoint\nHttpResponse<String> r = HttpClient.newHttpClient().send(HttpRequest.newBuilder(URI.create(apiEndpoint)).GET().build(), BodyHandlers.ofString());\nif (r.statusCode() >= 500) throw new IllegalStateException(\"GitHub endpoint unhealthy: \" + apiEndpoint);","typeGuard":null,"tryCatchPattern":"try { client.convertAppManifest(endpoint, code); } catch (IllegalStateException e) { retryWithBackoff(3, e); }","preventionTips":["Confirm DNS/firewall/proxy allow the SonarQube server to reach the GHES host","Trust the GHES certificate in the JVM truststore","Correct the apiEndpoint before starting the manifest flow","Monitor network paths between SonarQube and GitHub"],"tags":["github","io","network","alm-binding"],"backgroundTag":"network-request-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"}