iflytek/astron-agent · critical · BusinessException

MODEL_API_KEY_NOT_FOUND

MODEL_API_KEY_NOT_FOUND

Error message

BusinessException(ResponseEnum.MODEL_API_KEY_NOT_FOUND)

What it means

decryptApiKey needs the platform RSA private key to decrypt client-submitted API keys. It loads it from the config_info table (category=MODEL_SECRET_KEY, code=private_key, is_valid=1). If no such active config row exists, the service cannot decrypt anything and throws MODEL_API_KEY_NOT_FOUND — this is a server-side configuration problem, not a user input problem.

Solutions

  1. Insert a valid config row: category='MODEL_SECRET_KEY', code='private_key', is_valid=1, value=the RSA private key used at encryption time
  2. Verify the backend is connected to the intended database and query config_info to confirm the row exists and is_valid=1
  3. Re-run the environment's config seeding/migration scripts after fresh deployments or DB restores
  4. If keys were rotated, ensure the row's value matches the public key that encrypted the client-submitted api keys

Example fix

-- before: row missing/invalid
SELECT * FROM config_info WHERE category='MODEL_SECRET_KEY' AND code='private_key' AND is_valid=1; -- 0 rows
-- after
INSERT INTO config_info (category, code, value, is_valid) VALUES ('MODEL_SECRET_KEY','private_key','-----BEGIN RSA PRIVATE KEY-----...',1);
Defensive patterns

Strategy: validation

Validate before calling

ConfigInfo key = configInfoMapper.selectOne(new LambdaQueryWrapper<ConfigInfo>()
    .eq(ConfigInfo::getCategory, "MODEL_SECRET_KEY")
    .eq(ConfigInfo::getCode, "private_key")
    .eq(ConfigInfo::getIsValid, 1));
if (key == null) throw new IllegalStateException("MODEL_SECRET_KEY/private_key config missing; seed config_info before accepting model registrations");

Type guard

boolean rsaKeyConfigPresent() { return configInfoMapper.selectCount(new LambdaQueryWrapper<ConfigInfo>().eq(ConfigInfo::getCategory,"MODEL_SECRET_KEY").eq(ConfigInfo::getCode,"private_key").eq(ConfigInfo::getIsValid,1)) > 0; }

Try / catch

try { modelService.validateModel(req); } catch (BusinessException e) { if (ResponseEnum.MODEL_API_KEY_NOT_FOUND.equals(e.getResponseEnum())) { alertOpsToSeedConfig(); return 503-config-missing; } throw e; }

Prevention

When it happens

Trigger: Calling validateModel with a submitted apiKey that must be decrypted (apiKeyMasked false or id null) while the config_info table has no valid MODEL_SECRET_KEY/private_key row: fresh environment never seeded with the key, key row marked invalid, or wrong DB pointed at.

Common situations: New deployments missing the config seed SQL; operators rotating keys by invalidating the old row but failing to insert the new one; environment uses a different database than the one that was provisioned; key category/code renamed.

Understand the failure class

Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/325067bccc60b8e8. Report an issue: GitHub.

Appendix: source

Thrown at console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/model/ModelService.java:186

            log.error("Model validation failed, url={}, err={}", url, e.getMessage(), e);
            throw e;
        } catch (HttpClientErrorException | HttpServerErrorException e) {
            log.error("Model interface call failed, url={}, http={}, body={}", url, e.getStatusCode(), e.getResponseBodyAsString(), e);
            throw new BusinessException(ResponseEnum.MODEL_APIKEY_ERROR);
        } catch (Exception e) {
            log.error("Model validation failed, url={}, err={}", url, e.getMessage(), e);
            throw new BusinessException(ResponseEnum.MODEL_CHECK_FAILED);
        }
    }


    private String decryptApiKey(String apiKey) {
        ConfigInfo modelSecretKey = configInfoMapper.selectOne(Wrappers.<ConfigInfo>lambdaQuery()
                .eq(ConfigInfo::getCategory, "MODEL_SECRET_KEY")
                .eq(ConfigInfo::getCode, "private_key")
                .eq(ConfigInfo::getIsValid, 1));
        if (modelSecretKey == null) {
            throw new BusinessException(ResponseEnum.MODEL_API_KEY_NOT_FOUND);
        }

        try {
            RSAPrivateKey privateKey = RSAUtil.loadPrivateKey(modelSecretKey.getValue());
            return RSAUtil.decryptByPrivateKeyBase64(apiKey, privateKey);
        } catch (Exception e) {
            log.error("Decrypt API Key failed", e);
            throw new BusinessException(ResponseEnum.MODEL_APIKEY_LOAD_ERROR);
        }
    }

    private Map<String, Object> buildValidationPayload(String modelDomain, String provider) {
        if (PROVIDER_GOOGLE.equals(provider)) {
            Map<String, Object> textPart = new HashMap<>();
            textPart.put("text", "Hello!");

            Map<String, Object> content = new HashMap<>();
            content.put("role", "user");

View on GitHub (pinned to 5e758547a8)