appsmithorg/appsmith · error · AppsmithPluginException
PE-DSE-5003
PE-DSE-5003
Error message
The provided SSH key could not be parsed.
What it means
Thrown by SSHUtils.createSSHTunnel while reading the uploaded private key bytes into a string. The first try-with-resources reads key.getDecodedContent() line by line; any IOException (e.g. malformed byte sequence under UTF-8, truncated content) is wrapped as PLUGIN_DATASOURCE_ARGUMENT_ERROR with the SSH_KEY_PARSING_ERROR_MSG prefix and the underlying exception chained.
Source
Thrown at app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/SSHUtils.java:91
* folder. However, in our case because we cannot allow users to add trusted public keys in known_hosts
* folder for cloud hosted instances I am turning this check off.
*/
client.addHostKeyVerifier(new PromiscuousVerifier());
client.connect(sshHost, sshPort);
Reader targetReader = new InputStreamReader(new ByteArrayInputStream(key.getDecodedContent()));
String keyContent;
KeyProvider keyFile = null;
try (Reader reader = new StringReader(new String(key.getDecodedContent(), StandardCharsets.UTF_8));
BufferedReader bufferedReader = new BufferedReader(reader)) {
StringBuilder sb = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
sb.append(line).append("\n");
}
keyContent = sb.toString();
} catch (IOException e) {
throw new AppsmithPluginException(
AppsmithPluginError.PLUGIN_DATASOURCE_ARGUMENT_ERROR,
SSH_KEY_PARSING_ERROR_MSG + e.getMessage(),
e);
}
try {
if (keyContent.contains(OPENSSH_PEM_HEADER)) {
// Use BouncyCastle to handle OpenSSH keys
if (Security.getProvider("BC") == null) {
Security.addProvider(new BouncyCastleProvider());
}
OpenSSHKeyFile openSSHKeyFile = new OpenSSHKeyFile();
openSSHKeyFile.init(new StringReader(keyContent));
keyFile = openSSHKeyFile;
} else if (keyContent.contains(PKCS_8_PEM_HEADER) || keyContent.contains(PKCS_1_PEM_HEADER)) {
// Handle PEM (PKCS#8) and RSA PEM formats
PKCS8KeyFile pkcs8KeyFile = new PKCS8KeyFile();
pkcs8KeyFile.init(new StringReader(keyContent));
keyFile = pkcs8KeyFile;View on GitHub (pinned to 8cd9021c24)
Solutions
- Re-export the private key in OpenSSH or PEM format: ssh-keygen -p -f id_rsa -m PEM, then re-upload.
- Open the key file in a text editor and confirm it begins with -----BEGIN OPENSSH PRIVATE KEY----- or -----BEGIN RSA PRIVATE KEY----- / -----BEGIN PRIVATE KEY-----.
- Ensure no trailing whitespace or BOM is introduced when copy/pasting; upload the raw file rather than pasting its contents.
- If the key was generated by a cloud portal (AWS, GCP), download the provided .pem directly without re-encoding.
Example fix
// before
try (Reader reader = new StringReader(new String(key.getDecodedContent(), StandardCharsets.UTF_8))) { ... }
// after - tolerate malformed bytes by reading with a replace decoder and validating structure
String keyContent = new String(key.getDecodedContent(), StandardCharsets.UTF_8);
if (!keyContent.contains("PRIVATE KEY")) {
throw new AppsmithPluginException(
AppsmithPluginError.PLUGIN_DATASOURCE_ARGUMENT_ERROR,
SSH_KEY_PARSING_ERROR_MSG + "content does not look like a PEM/OpenSSH private key");
} Defensive patterns
Strategy: validation
Validate before calling
byte[] content = key.getDecodedContent();
if (content == null || content.length == 0) {
throw new IllegalArgumentException("SSH key content is empty");
}
String preview = new String(content, StandardCharsets.UTF_8);
if (!preview.contains("PRIVATE KEY")) {
throw new IllegalArgumentException("Uploaded file does not look like a private key");
}
// safe to proceed to SSHUtils.createSSHTunnel Type guard
public static boolean looksLikePrivateKey(byte[] content) {
if (content == null || content.length == 0) return false;
String s = new String(content, StandardCharsets.UTF_8);
return s.contains("PRIVATE KEY");
} Try / catch
try {
SSHTunnelContext ctx = SSHUtils.createSSHTunnel(host, port, user, key, dbHost, dbPort);
} catch (AppsmithPluginException e) {
if (e.getMessage() != null && e.getMessage().startsWith(SSH_KEY_PARSING_ERROR_MSG)) {
// surface a user-actionable message about key format
throw new IllegalArgumentException("SSH key could not be read; re-export in OpenSSH/PEM format", e);
}
throw e;
} Prevention
- Validate key content is non-empty and contains a PRIVATE KEY marker before upload.
- Re-export keys via ssh-keygen -m PEM to guarantee UTF-8 PEM output.
- Never paste keys through rich-text editors that may alter bytes.
When it happens
Trigger: Uploading an SSH private key whose bytes are not valid UTF-8 (binary corruption, double-encoded base64), an empty key file, or a key whose content was truncated during upload. The exception is raised before any format detection occurs - it is purely about reading the bytes.
Common situations: Pasting a key with stray terminal control characters; uploading a .ppk (PuTTY) key which is not raw PEM; a copy/paste that lost the BEGIN/END lines; encoding mismatches when the key was stored as base64-of-base64.
Related errors
AI-assisted analysis of appsmithorg/appsmith@8cd9021c24 (2026-08-12).
Data as JSON: /api/errors/d2257430a086d6d9.
Report an issue: GitHub.