SonarSource/sonarqube · error · IllegalArgumentException
Cannot mint a GitHub installation token for project '%s': in
Error message
Cannot mint a GitHub installation token for project '%s': invalid GitHub App configuration: %s
What it means
GithubInstallationTokenProviderImpl.mint() wraps IllegalArgumentException from building/validating the GitHub App configuration into an IllegalArgumentException with the project key and the underlying reason, distinguishing 'binding exists but its GitHub App configuration is broken' from 'project not bound'. Callers receive a 400-class error instead of a 404.
Source
Thrown at server/sonar-webserver-common/src/main/java/org/sonar/server/common/almsettings/github/GithubInstallationTokenProviderImpl.java:128
private Optional<GithubInstallationToken> mint(String projectKey, AlmSettingDto almSetting, String almRepo) {
String safeProjectKey = sanitizeForLog(projectKey);
String safeAlmRepo = sanitizeForLog(almRepo);
GithubAppConfiguration githubAppConfiguration;
try {
// TOKEN_MINTING_PERMISSIONS, not the plain default: a minted token is pointless if the GitHub
// App doesn't have 'contents: write' to push the remediation commit it's minted for. Most
// already-installed apps predate this requirement — there's no in-product way to prompt them
// to re-approve, so the wrapped message below is the only guidance an admin gets.
githubAppConfiguration = githubGlobalSettingsValidator.validate(almSetting, GithubAppPermissions.TOKEN_MINTING_PERMISSIONS);
} catch (IllegalArgumentException e) {
// Wrapped (with the project key) rather than swallowed to Optional.empty(): unlike the checks
// above, this isn't a "not bound" case — the binding exists, its GitHub App configuration is
// just broken (bad credentials, missing permissions, unreachable API, ...). Wrapping instead of
// rethrowing as-is adds context in one throw (S2139) while still getting the caller a distinct
// 400 instead of the same 404 as a genuinely unbound project.
throw new IllegalArgumentException(
format("Cannot mint a GitHub installation token for project '%s': invalid GitHub App configuration: %s", safeProjectKey, e.getMessage()), e);
}
Optional<Long> installationId = githubApplicationClient.getInstallationId(githubAppConfiguration, almRepo);
if (installationId.isEmpty()) {
LOG.warn("Cannot mint a GitHub installation token for project '{}': GitHub App is not installed on repository '{}'", safeProjectKey, safeAlmRepo);
return Optional.empty();
}
String repositoryName = bareRepositoryName(almRepo);
Optional<ExpiringAppInstallationToken> token = githubApplicationClient.createAppInstallationToken(githubAppConfiguration, installationId.get(), repositoryName);
if (token.isEmpty()) {
LOG.warn("Failed to mint a GitHub installation token for project '{}' (repository '{}')", safeProjectKey, safeAlmRepo);
throw new ServerException(HTTP_INTERNAL_ERROR,
format("Failed to mint a GitHub installation token for project '%s': GitHub App API call failed", safeProjectKey));
}
return Optional.of(new GithubInstallationToken(View on GitHub (pinned to 184c821202)
Solutions
- Fix the GitHub App configuration in Administration > DevOps Platform Integrations > GitHub: correct App ID, Client ID, and a valid PEM private key
- Ensure the private key includes proper PEM headers and newlines (avoid flattening it in env vars)
- Verify SonarQube can reach the GitHub API URL (proxy/TLS) and the App is still installed on the target org/repository
- Inspect the embedded cause message for the specific validation failure
Example fix
// before GITHUB_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n..." # literal \n, invalid PEM // after store key verbatim (real newlines) e.g. in a mounted secret file and load it
Defensive patterns
Strategy: validation
Validate before calling
// sanity-check GitHub App config before minting
const pemOk = /-----BEGIN (RSA )?PRIVATE KEY-----[\s\S]+-----END (RSA )?PRIVATE KEY-----/.test(privateKey);
if (!appId || !clientId || !pemOk) throw new Error('GitHub App config incomplete: App ID, Client ID and valid PEM private key required'); Type guard
null
Try / catch
try {
const t = githubInstallationTokenProvider.getNewInstallationToken(projectKey);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("invalid GitHub App configuration")) {
// fix App ID / private key / API URL; cause has the detail
} else throw e;
} Prevention
- Load the private key from a file/secret preserving PEM newlines
- Re-validate integration settings after rotating the GitHub App key
- Confirm App installation on the target org before minting tokens
- Test the GitHub API URL reachability from the SonarQube host
When it happens
Trigger: Requesting a GitHub installation token for a project whose ALM binding exists but whose GitHub App configuration fails validation: invalid App ID/private key (malformed PEM), wrong client ID, missing permissions, or unreachable GitHub API discovered during configuration setup.
Common situations: Rotated or mis-pasted GitHub App private key; App ID changed after re-creating the App; typo in GitHub API URL; private key stored without newline preservation in env/secret manager.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Missing permissions; permission granted on %s
- Missing URL
- Invalid URL, %s
- Only http and https schemes are supported
- Invalid GitHub URL
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/f53882eafa64a3c9.
Report an issue: GitHub.