{"record":{"id":"e6ab3431a6358b3b","repo":"alibaba/spring-ai-alibaba","slug":"apikey-e6ab34","errorCode":null,"errorMessage":"解密apiKey失败: {}","messagePattern":"解密apiKey失败: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-start/src/main/java/com/alibaba/cloud/ai/studio/admin/service/impl/ModelConfigBridgeServiceImpl.java","lineNumber":347,"sourceCode":"     */\n    private ModelConfigDO buildModelConfigDOFromModelConfigInfo(ModelConfigInfo modelConfigInfo, Long id) {\n        try {\n            ProviderConfigInfo providerDetail = providerManager.getProviderDetail(modelConfigInfo.getProvider(), false);\n            if (providerDetail == null) {\n                return null;\n            }\n\n            ModelCredential credential = providerDetail.getCredential();\n            if (credential == null) {\n                return null;\n            }\n\n            String apiKey = credential.getApiKey();\n            if (StringUtils.isNotBlank(apiKey)) {\n                try {\n                    apiKey = RSACryptUtils.decrypt(apiKey);\n                } catch (Exception e) {\n                    log.warn(\"解密apiKey失败: {}\", e.getMessage());\n                }\n            }\n\n            String baseUrl = credential.getEndpoint();\n            if (StringUtils.isNotBlank(baseUrl)) {\n                if (baseUrl.endsWith(\"/v1\") || baseUrl.endsWith(\"/v1/\")) {\n                    baseUrl = baseUrl.replaceAll(\"/v1/?$\", \"\");\n                }\n            } else {\n                baseUrl = getDefaultBaseUrl(modelConfigInfo.getProvider());\n            }\n\n            return ModelConfigDO.builder()\n                    .id(id)\n                    .name(modelConfigInfo.getName())\n                    .provider(modelConfigInfo.getProvider().toLowerCase())\n                    .modelName(modelConfigInfo.getModelId())\n                    .baseUrl(baseUrl)","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-start/src/main/java/com/alibaba/cloud/ai/studio/admin/service/impl/ModelConfigBridgeServiceImpl.java#L329-L365","documentation":"buildModelConfigDOFromModelConfigInfo decrypts the provider's apiKey with RSACryptUtils.decrypt; on failure it logs this warning and continues using the encrypted value. The built ModelConfigDO will contain ciphertext as the API key, causing authentication failures on model calls.","triggerScenarios":"Credential apiKey stored under a different RSA key pair than the current RSACryptUtils configuration, or the stored value was never encrypted (plaintext inserted directly).","commonSituations":"Environment migration with different RSA keys; key rotation without re-encrypting secrets; manual DB edits inserting plaintext keys; shared DB across deployments with distinct key configs.","solutions":["Re-enter the API key via the admin UI so it is encrypted with the current key","Align RSACryptUtils key configuration across environments (same private key as the encrypting environment)","Re-encrypt all stored credentials after key rotation using a migration script","Monitor for this warning in logs — model calls will fail auth downstream"],"exampleFix":"// before\nString apiKey = credential.getApiKey(); // ciphertext used directly\n// after\nString apiKey = credential.getApiKey();\nif (!isPlaintextValid(apiKey)) { reSaveCredentialWithCurrentKey(provider); }","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { chatWith(config); } catch (AuthenticationException e) { reSaveApiKeyWithCurrentRsaKey(provider); }","preventionTips":["Align RSA keys across environments sharing a database","Rotate keys with a credential re-encryption migration","Enter keys only through the admin UI","Monitor logs for this warning"],"tags":["encryption","api-key","rsa","credentials"],"backgroundTag":"invalid-config-value","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}