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

  1. Fix the GitHub App configuration in Administration > DevOps Platform Integrations > GitHub: correct App ID, Client ID, and a valid PEM private key
  2. Ensure the private key includes proper PEM headers and newlines (avoid flattening it in env vars)
  3. Verify SonarQube can reach the GitHub API URL (proxy/TLS) and the App is still installed on the target org/repository
  4. 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

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


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/f53882eafa64a3c9. Report an issue: GitHub.