{"record":{"id":"64bbe9b093eb36f0","repo":"SonarSource/sonarqube","slug":"cannot-mint-a-github-installation-token-for-projec-64bbe9","errorCode":null,"errorMessage":"Cannot mint a GitHub installation token for project '{}': GitHub App is not installed on repository '{}'","messagePattern":"Cannot mint a GitHub installation token for project '(.+?)': GitHub App is not installed on repository '(.+?)'","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/sonar-webserver-common/src/main/java/org/sonar/server/common/almsettings/github/GithubInstallationTokenProviderImpl.java","lineNumber":134,"sourceCode":"    try {\n      // TOKEN_MINTING_PERMISSIONS, not the plain default: a minted token is pointless if the GitHub\n      // App doesn't have 'contents: write' to push the remediation commit it's minted for. Most\n      // already-installed apps predate this requirement — there's no in-product way to prompt them\n      // to re-approve, so the wrapped message below is the only guidance an admin gets.\n      githubAppConfiguration = githubGlobalSettingsValidator.validate(almSetting, GithubAppPermissions.TOKEN_MINTING_PERMISSIONS);\n    } catch (IllegalArgumentException e) {\n      // Wrapped (with the project key) rather than swallowed to Optional.empty(): unlike the checks\n      // above, this isn't a \"not bound\" case — the binding exists, its GitHub App configuration is\n      // just broken (bad credentials, missing permissions, unreachable API, ...). Wrapping instead of\n      // rethrowing as-is adds context in one throw (S2139) while still getting the caller a distinct\n      // 400 instead of the same 404 as a genuinely unbound project.\n      throw new IllegalArgumentException(\n        format(\"Cannot mint a GitHub installation token for project '%s': invalid GitHub App configuration: %s\", safeProjectKey, e.getMessage()), e);\n    }\n\n    Optional<Long> installationId = githubApplicationClient.getInstallationId(githubAppConfiguration, almRepo);\n    if (installationId.isEmpty()) {\n      LOG.warn(\"Cannot mint a GitHub installation token for project '{}': GitHub App is not installed on repository '{}'\", safeProjectKey, safeAlmRepo);\n      return Optional.empty();\n    }\n\n    String repositoryName = bareRepositoryName(almRepo);\n    Optional<ExpiringAppInstallationToken> token = githubApplicationClient.createAppInstallationToken(githubAppConfiguration, installationId.get(), repositoryName);\n    if (token.isEmpty()) {\n      LOG.warn(\"Failed to mint a GitHub installation token for project '{}' (repository '{}')\", safeProjectKey, safeAlmRepo);\n      throw new ServerException(HTTP_INTERNAL_ERROR,\n        format(\"Failed to mint a GitHub installation token for project '%s': GitHub App API call failed\", safeProjectKey));\n    }\n\n    return Optional.of(new GithubInstallationToken(\n      token.get().getValue(), token.get().getExpiresAt().format(ISO_OFFSET_DATE_TIME)));\n  }\n\n  /**\n   * Strips CR/LF from user-controlled values (project key, ALM repo slug) before logging them, so a\n   * crafted value cannot forge extra log lines/entries (CWE-117).","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-common/src/main/java/org/sonar/server/common/almsettings/github/GithubInstallationTokenProviderImpl.java#L116-L152","documentation":"GithubInstallationTokenProviderImpl.mint logs this warning and returns Optional.empty() when githubApplicationClient.getInstallationId finds no GitHub App installation for the configured app on the bound repository. The project and its GitHub App binding are valid, but at the GitHub side the App is not installed (or not installed on the org/repo containing the bound repository), so no installation ID — and thus no token — can be obtained.","triggerScenarios":"Minting for a project bound to repository 'org/repo' where the SonarQube GitHub App has no installation covering that repository: app never installed on the org, installed only on selected repos excluding this one, or almRepo path typos/mismatch (wrong org name, repo renamed).","commonSituations":"New repo created after the App was installed on a subset of repositories; repo transferred to another org where the App isn't installed; GitHub App uninstalled from the organization; almRepo configured with a different casing/path than actual GitHub repo.","solutions":["Install the SonarQube GitHub App on the organization or repository: GitHub > Settings > Integrations > Applications > SonarQube App > Configure > select the repository/org.","If the App is installed with 'select repositories', add the bound repository to the selection.","Verify almRepo matches the actual GitHub repository full name (org/repo) and update the SonarQube binding if it was renamed or transferred.","Check the GitHub App configuration in SonarQube (api/alm_integrations/view_github) points to the right App ID/endpoint.","In automation, treat the empty Optional as 'install the App first' rather than retrying."],"exampleFix":"// before: binding repo 'acme/payments-service', App installed only on 'acme/webapp'\n// after (in GitHub): Settings > Applications > SonarQube > Repository access -> add 'payments-service'\n// or in SonarQube if repo moved:\nPOST api/alm_settings/set_github -d project=payments -d almSetting=github-company -d repositoryName=acme-new/payments-service","handlingStrategy":"fallback","validationCode":"# Verify App installation via GitHub API before minting\nSTATUS=$(curl -s -o /dev/null -w '%{http_code}' -H \"Authorization: Bearer $GH_APP_JWT\" \"https://api.github.com/repos/$ORG/$REPO/installation\")\n[ \"$STATUS\" = \"200\" ] || { echo \"GitHub App not installed on $ORG/$REPO; install it first\" >&2; exit 1; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Install the SonarQube GitHub App org-wide (or maintain the repo allowlist) before onboarding projects.","After repo renames or org transfers, update the SonarQube binding and confirm installation coverage.","Re-check installation after GitHub App upgrades or uninstalls."],"tags":["github","github-app","app-not-installed","alm-integration"],"backgroundTag":"entity-not-found","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"}