{"record":{"id":"f6541472ee2eb873","repo":"SonarSource/sonarqube","slug":"failed-to-create-the-github-app-from-manifest-git","errorCode":null,"errorMessage":"Failed to create the GitHub App from manifest. GitHub returned code ","messagePattern":"Failed to create the GitHub App from manifest\\. 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":418,"sourceCode":"      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);\n    }\n  }\n\n  @Override\n  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","sourceCodeStart":400,"sourceCodeEnd":436,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-alm-client/src/main/java/org/sonar/alm/client/github/GithubApplicationClientImpl.java#L400-L436","documentation":"convertAppManifest converts a GitHub App manifest code into App credentials after a manifest-based App creation. If GitHub returns a status other than 201 or 200, the body is logged at DEBUG and this IllegalStateException is thrown with the returned code. It means the manifest conversion endpoint rejected the request.","triggerScenarios":"Calling convertAppManifest(apiEndpoint, code) when the POST response code is not 201/200 — expired or already-used manifest code, wrong apiEndpoint, or GitHub server error.","commonSituations":"User delayed between creating the App from manifest and SonarQube converting it (code expires in ~10 minutes), the conversion was already completed once (codes are single-use), incorrect GHES API endpoint configured.","solutions":["Restart the App creation flow from the beginning to get a fresh manifest code and convert it promptly.","Verify the apiEndpoint matches your GitHub instance (https://api.github.com or GHES host).","Enable DEBUG logging to inspect the error response body from GitHub.","Check GitHub status for outages if a 5xx code is reported and retry."],"exampleFix":"// before\nclient.convertAppManifest(endpoint, oldCode); // code already used/expired\n// after\nString freshCode = redoAppManifestFlow(); client.convertAppManifest(endpoint, freshCode);","handlingStrategy":"retry","validationCode":"// use the code immediately after obtaining it\nif (code == null || code.isBlank()) throw new IllegalArgumentException(\"Manifest code required\");\nInstant obtainedAt = Instant.now(); if (Duration.between(obtainedAt, Instant.now()).toMinutes() > 8) throw new IllegalStateException(\"Manifest code likely expired; restart flow\");","typeGuard":null,"tryCatchPattern":"try { client.convertAppManifest(endpoint, code); } catch (IllegalStateException e) { if (e.getMessage().contains(\"returned code 5\")) retryWithBackoff(3, e); else throw e; }","preventionTips":["Convert the manifest code within minutes of App creation","Never reuse a manifest code — restart the flow for a fresh one","Verify the apiEndpoint matches the instance the App was created on","Watch DEBUG logs for the GitHub error body on non-201 responses"],"tags":["github","http","app-manifest","alm-binding"],"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"}