iflytek/astron-agent · error · BusinessException

MODEL_APIKEY_ERROR

MODEL_APIKEY_ERROR

Error message

BusinessException(ResponseEnum.MODEL_APIKEY_ERROR)

What it means

When the probe request to the model endpoint returns an HTTP 4xx/5xx (HttpClientErrorException/HttpServerErrorException), validateModel translates it into MODEL_APIKEY_ERROR. The service assumes an HTTP error from an OpenAI-compatible endpoint is most likely caused by an invalid API key (401/403), so it surfaces a credentials-oriented error to the user.

Solutions

  1. Check the exact HTTP status logged ('Model interface call failed, http=...') to distinguish 401/403 (key) from 404 (model name/path) or 5xx (server)
  2. Re-enter the API key carefully — no whitespace, correct prefix, currently valid for the account
  3. Confirm the model name/path exists on the endpoint and the account has quota/access
  4. Retry if the status is 5xx/429 since the error may not be key-related at all

Example fix

// before
req.setApiKey("  sk-abc...   "); // trailing whitespace -> 401
// after
req.setApiKey(apiKey.trim()); // and verify 200 via curl before saving
Defensive patterns

Strategy: try-catch

Validate before calling

// distinguish key errors from other HTTP failures before assuming the key is bad
try { probe(endpoint, apiKey); } catch (HttpStatusCodeException e) { log.warn("probe http={} body={}", e.getStatusCode(), e.getResponseBodyAsString()); if (e.getStatusCode().value() >= 500 || e.getStatusCode().value() == 429) { /* not a key problem; retry later */ } }

Type guard

boolean isAuthRelatedStatus(HttpStatus s) { return s == HttpStatus.UNAUTHORIZED || s == HttpStatus.FORBIDDEN; }

Try / catch

try { modelService.validateModel(req); } catch (BusinessException e) { if (ResponseEnum.MODEL_APIKEY_ERROR.equals(e.getResponseEnum())) { promptUserToReenterApiKey(); return 401-invalid-key; } throw e; }

Prevention

When it happens

Trigger: Calling validateModel where the endpoint responds with any 4xx/5xx status — invalid/expired API key (401), wrong key format, model name not found on the server (404), quota/rate issues (429), or server-side 5xx.

Common situations: Copied API keys with whitespace or truncation; key rotated on the vendor side; wrong model name so the provider 404s; endpoint behind IP allowlist rejecting the server; upstream provider outage causing 5xx misreported as a key problem.

Related errors


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

Appendix: source

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

        final HttpHeaders headers = buildAuthHeaders(decryptedApiKey, provider);

        try {
            String responseBody = doPostModelApi(url, requestBody, headers);
            if (isValidModelResponse(responseBody, provider)) {
                log.info("Model validation passed, domain={}, endpoint={}", request.getDomain(), url);
                request.setApiKey(decryptedApiKey);
                request.setEndpoint(url);
                request.setProvider(provider);
                saveOrUpdateModel(request);
                return "Model validation passed";
            }
            throw new BusinessException(ResponseEnum.MODEL_NOT_COMPATIBLE_OPENAI);
        } catch (BusinessException e) {
            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());

View on GitHub (pinned to 5e758547a8)