{"record":{"id":"1f079eba1d74a49a","repo":"iflytek/astron-agent","slug":"model-apikey-error","errorCode":"MODEL_APIKEY_ERROR","errorMessage":"BusinessException(ResponseEnum.MODEL_APIKEY_ERROR)","messagePattern":"BusinessException\\(ResponseEnum\\.MODEL_APIKEY_ERROR\\)","errorType":"error_code","errorClass":"BusinessException","httpStatus":null,"severity":"error","filePath":"console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/model/ModelService.java","lineNumber":172,"sourceCode":"        final HttpHeaders headers = buildAuthHeaders(decryptedApiKey, provider);\n\n        try {\n            String responseBody = doPostModelApi(url, requestBody, headers);\n            if (isValidModelResponse(responseBody, provider)) {\n                log.info(\"Model validation passed, domain={}, endpoint={}\", request.getDomain(), url);\n                request.setApiKey(decryptedApiKey);\n                request.setEndpoint(url);\n                request.setProvider(provider);\n                saveOrUpdateModel(request);\n                return \"Model validation passed\";\n            }\n            throw new BusinessException(ResponseEnum.MODEL_NOT_COMPATIBLE_OPENAI);\n        } catch (BusinessException e) {\n            log.error(\"Model validation failed, url={}, err={}\", url, e.getMessage(), e);\n            throw e;\n        } catch (HttpClientErrorException | HttpServerErrorException e) {\n            log.error(\"Model interface call failed, url={}, http={}, body={}\", url, e.getStatusCode(), e.getResponseBodyAsString(), e);\n            throw new BusinessException(ResponseEnum.MODEL_APIKEY_ERROR);\n        } catch (Exception e) {\n            log.error(\"Model validation failed, url={}, err={}\", url, e.getMessage(), e);\n            throw new BusinessException(ResponseEnum.MODEL_CHECK_FAILED);\n        }\n    }\n\n\n    private String decryptApiKey(String apiKey) {\n        ConfigInfo modelSecretKey = configInfoMapper.selectOne(Wrappers.<ConfigInfo>lambdaQuery()\n                .eq(ConfigInfo::getCategory, \"MODEL_SECRET_KEY\")\n                .eq(ConfigInfo::getCode, \"private_key\")\n                .eq(ConfigInfo::getIsValid, 1));\n        if (modelSecretKey == null) {\n            throw new BusinessException(ResponseEnum.MODEL_API_KEY_NOT_FOUND);\n        }\n\n        try {\n            RSAPrivateKey privateKey = RSAUtil.loadPrivateKey(modelSecretKey.getValue());","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/model/ModelService.java#L154-L190","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the exact HTTP status logged ('Model interface call failed, http=...') to distinguish 401/403 (key) from 404 (model name/path) or 5xx (server)","Re-enter the API key carefully — no whitespace, correct prefix, currently valid for the account","Confirm the model name/path exists on the endpoint and the account has quota/access","Retry if the status is 5xx/429 since the error may not be key-related at all"],"exampleFix":"// before\nreq.setApiKey(\"  sk-abc...   \"); // trailing whitespace -> 401\n// after\nreq.setApiKey(apiKey.trim()); // and verify 200 via curl before saving","handlingStrategy":"try-catch","validationCode":"// distinguish key errors from other HTTP failures before assuming the key is bad\ntry { 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 */ } }","typeGuard":"boolean isAuthRelatedStatus(HttpStatus s) { return s == HttpStatus.UNAUTHORIZED || s == HttpStatus.FORBIDDEN; }","tryCatchPattern":"try { modelService.validateModel(req); } catch (BusinessException e) { if (ResponseEnum.MODEL_APIKEY_ERROR.equals(e.getResponseEnum())) { promptUserToReenterApiKey(); return 401-invalid-key; } throw e; }","preventionTips":["Validate the API key against the provider with curl before submitting","Trim whitespace and avoid copying truncated keys","Check the logged HTTP status — 404/429/5xx are often not key problems","Rotate keys centrally and update the platform before old ones expire"],"tags":["api-key","http","authentication","model-validation"],"backgroundTag":"invalid-api-key","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}