SonarSource/sonarqube · error · IllegalArgumentException
Failed to decode Github Application private key
Error message
Failed to decode Github Application private key
What it means
Thrown by GithubAppSecurityImpl.readApplicationPrivateKey when the BouncyCastle PemReader parses the provided private key string but no PEM object can be read (parse returns null). The key text is not a valid PEM-encoded block.
Source
Thrown at server/sonar-alm-client/src/main/java/org/sonar/alm/client/github/security/GithubAppSecurityImpl.java:77
LocalDateTime expiresAt = now.plus(AppToken.EXPIRATION_PERIOD_IN_MINUTES, ChronoUnit.MINUTES);
ZoneOffset offset = clock.getZone().getRules().getOffset(now);
Date nowDate = Date.from(now.toInstant(offset));
Date expiresAtDate = Date.from(expiresAt.toInstant(offset));
JWTCreator.Builder builder = JWT.create()
.withIssuer(String.valueOf(appId))
.withIssuedAt(nowDate)
.withExpiresAt(expiresAtDate);
return new AppToken(builder.sign(algorithm));
}
private static Algorithm readApplicationPrivateKey(long appId, String encodedPrivateKey) {
byte[] decodedPrivateKey = encodedPrivateKey.getBytes(UTF_8);
try (PemReader pemReader = new PemReader(new InputStreamReader(new ByteArrayInputStream(decodedPrivateKey)))) {
Security.addProvider(new BouncyCastleProvider());
PemObject pemObject = pemReader.readPemObject();
if (pemObject == null) {
throw new IllegalArgumentException("Failed to decode Github Application private key");
}
PKCS8EncodedKeySpec keySpec1 = new PKCS8EncodedKeySpec(pemObject.getContent());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec1);
return Algorithm.RSA256(new RSAKeyProvider() {
@Override
public RSAPublicKey getPublicKeyById(String keyId) {
throw new UnsupportedOperationException("getPublicKeyById not implemented");
}
@Override
public RSAPrivateKey getPrivateKey() {
return (RSAPrivateKey) privateKey;
}
@Override
public String getPrivateKeyId() {View on GitHub (pinned to 184c821202)
Solutions
- Paste the complete .pem file contents including '-----BEGIN PRIVATE KEY-----' and '-----END PRIVATE KEY-----' lines
- Download the private key again from the GitHub App settings page and reconfigure
- Ensure the key was not truncated or re-encoded (e.g. double base64) when stored in the settings
Example fix
// before: privateKey = "MIIEvQIBADANBg..." (raw base64, no PEM headers) // after: privateKey = "-----BEGIN PRIVATE KEY-----\nMIIEvQ...\n-----END PRIVATE KEY-----";
Defensive patterns
Strategy: validation
Validate before calling
function isValidPem(key) {
return typeof key === 'string' && /-----BEGIN (RSA )?PRIVATE KEY-----[\s\S]+-----END (RSA )?PRIVATE KEY-----/.test(key.trim());
} Try / catch
try { configureGithubApp(appId, privateKey); } catch (IllegalArgumentException e) { log("Private key is not valid PEM: " + e.getMessage()); } Prevention
- Paste the entire .pem file including BEGIN/END header and footer lines
- Store the key in a settings field that preserves newlines (no shell mangling)
- Validate the PEM structure client-side before submitting settings
When it happens
Trigger: readApplicationPrivateKey (via algorithm) receives a key whose bytes contain no recognizable '-----BEGIN ...-----' PEM structure, so pemReader.readPemObject() returns null.
Common situations: Key pasted without the BEGIN/END headers; key stored as raw base64 body only; placeholder or wrong value configured; key mangled by shell escaping or JSON escaping.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Missing URL
- Invalid URL, %s
- Only http and https schemes are supported
- Invalid GitHub URL
- Missing permissions; permission granted on %s
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/9ba247415c7c4b73.
Report an issue: GitHub.