{"record":{"id":"3945f3dabc632087","repo":"OtterMind/Chat2DB","slug":"api-privatekeynotfound","errorCode":"api.privateKeyNotFound","errorMessage":"api.privateKeyNotFound","messagePattern":"api\\.privateKeyNotFound","errorType":"exception","errorClass":"BusinessException","httpStatus":null,"severity":"error","filePath":"chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/db/DbWorkspaceDataSourceServiceImpl.java","lineNumber":231,"sourceCode":"        if (StringUtils.isNotBlank(dataSource.getHost())) {\n            dataSource.setHost(decryptToken(dataSource.getHost(), privateKey));\n        }\n        if (StringUtils.isNotBlank(dataSource.getUrl())) {\n            dataSource.setUrl(decryptToken(dataSource.getUrl(), privateKey));\n        }\n        if (StringUtils.isNotBlank(dataSource.getUser())) {\n            dataSource.setUser(decryptToken(dataSource.getUser(), privateKey));\n        }\n    }\n\n    private PrivateKey stringToPrivateKey(String privateKeyString) {\n        try {\n            byte[] keyBytes = Base64.getDecoder().decode(privateKeyString);\n            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);\n            KeyFactory keyFactory = KeyFactory.getInstance(\"RSA\");\n            return keyFactory.generatePrivate(keySpec);\n        } catch (Exception e) {\n            throw new BusinessException(\"api.privateKeyNotFound\");\n        }\n    }\n\n    private String decryptToken(String encryptedToken, PrivateKey privateKey) {\n        try {\n            Cipher cipher = Cipher.getInstance(\"RSA/ECB/PKCS1Padding\");\n            cipher.init(Cipher.DECRYPT_MODE, privateKey);\n            byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedToken));\n            return new String(decryptedBytes, StandardCharsets.UTF_8);\n        } catch (Exception e) {\n            log.error(\"decrypt token error\", e);\n            throw new BusinessException(\"api.decryptPasswordError\");\n        }\n    }\n\n    private String decryptString(String password) {\n        if (password == null || password.isEmpty()) {\n            return password;","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/OtterMind/Chat2DB/blob/5ee1e990e73fbcae1969dc554be254fedb3ab888/chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/db/DbWorkspaceDataSourceServiceImpl.java#L213-L249","documentation":"BusinessException 'api.privateKeyNotFound' from stringToPrivateKey when the organization-token string cannot be Base64-decoded into a valid PKCS8 RSA private key. The KeyFactory/KeySpec step throws, meaning the supplied key material is malformed or not actually a private key.","triggerScenarios":"decryptSensitiveFields receives a non-null organizationToken that is corrupt, truncated, not PKCS8 DER, or is a public key string. Base64.getDecoder().decode or KeyFactory.generatePrivate then fails.","commonSituations":"Org token overwritten with a placeholder; token from a different key pair (public key only); copy/paste truncation or whitespace in the token; key regenerated server-side but client holds a stale token.","solutions":["Re-authenticate to obtain a fresh organization token matching the server's current key pair.","Confirm the token is a PKCS8 private key (Base64 of DER, not PEM-wrapped or a public key).","Check for whitespace/newlines accidentally included in the token value.","Verify the server-side key provisioning generated a valid RSA private key."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// sanity check the token shape before use\nString tok = ctx.getOrganizationToken();\nif (tok == null || tok.length() < 100) throw new IllegalArgumentException(\"organization token looks invalid\");\ntry { Base64.getDecoder().decode(tok); } catch (IllegalArgumentException ex) { throw new IllegalArgumentException(\"token is not base64\"); }","typeGuard":null,"tryCatchPattern":"try { PrivateKey k = stringToPrivateKey(token); }\ncatch (BusinessException e) {\n    // recover by forcing re-auth rather than continuing with a bad key\n    throw new NeedLoggedInBusinessException();\n}","preventionTips":["Treat 'api.privateKeyNotFound' as an auth failure — re-authenticate to refresh the token.","Do not hand-edit or truncate the organization token.","Validate token is Base64 + reasonable length before passing to KeyFactory."],"tags":["encryption","rsa","auth","config"],"backgroundTag":null,"analyzedSha":"5ee1e990e73fbcae1969dc554be254fedb3ab888","analyzedAt":"2026-08-14T07:05:03.077Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}