iflytek/astron-agent · error
Tenant internal authentication is not configured…
Error message
Tenant internal authentication is not configured; verification was not sent
What it means
Within verify(), TenantInternalApiKey.requireConfigured(tenantInternalKey) throws IllegalStateException when the internal shared key used to authenticate the console to the tenant service is not configured. The catch block logs "Tenant internal authentication is not configured; verification was not sent" and returns Optional.empty() — the verification HTTP request is never sent.
Solutions
- Configure the tenant internal API key property/env var and restart the console backend.
- Verify the secret is actually mounted/injected (kubectl describe pod, env dump) in the deployment.
- Check that TenantInternalApiKey.requireConfigured's expected property name matches the configured key.
- Confirm the header name constant and key format expected by the tenant service.
Example fix
# before
# (internal key absent)
# after
tenant:
gateway:
internal-api-key: ${TENANT_INTERNAL_API_KEY} Defensive patterns
Strategy: validation
Validate before calling
// startup check TenantInternalApiKey.requireConfigured(tenantInternalKey); // throws early at boot if blank
Try / catch
Optional<String> appId = authClient.verify(apiKey, apiSecret);
if (appId.isEmpty()) {
auditLog.warn("verification not performed — check tenant internal key configuration");
return unauthorized();
} Prevention
- Inject the internal key as a k8s secret and mount it explicitly.
- Call requireConfigured during application startup, not per-request.
- Add the key to deployment checklists and config schema validation.
- Rotate console/tenant keys together to avoid drift.
When it happens
Trigger: verify() called with valid verifyAppAuthUrl/apiKey/apiSecret but the tenantInternalKey field (internal header key) is null/blank, so requireConfigured throws.
Common situations: Internal key property missing from application.yml/env after deployment; secret not mounted in k8s; key removed during config migration; wrong property name so the field never gets injected.
Understand the failure class
Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- RAGFLOW_API_TOKEN not configured in environment variables
- Tenant application credential verification is not…
- INTERNAL_SERVER_ERROR
- KEY_PARSE_FAILED
- MODEL_APIKEY_LOAD_ERROR
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/2a2a7d6f2c3c8e3f.
Report an issue: GitHub.
Appendix: source
Thrown at console/backend/hub/src/main/java/com/iflytek/astron/console/hub/service/gateway/impl/HttpTenantGatewayAuthClient.java:59
this.httpClient = httpClient;
this.verifyAppAuthUrl = verifyAppAuthUrl;
this.tenantInternalKey = tenantInternalKey;
}
@Override
public Optional<String> verify(String apiKey, String apiSecret) {
if (!StringUtils.hasText(verifyAppAuthUrl)
|| !StringUtils.hasText(apiKey)
|| !StringUtils.hasText(apiSecret)) {
log.warn("Tenant application credential verification is not configured or incomplete");
return Optional.empty();
}
String configuredInternalKey;
try {
configuredInternalKey =
TenantInternalApiKey.requireConfigured(tenantInternalKey);
} catch (IllegalStateException exception) {
log.warn("Tenant internal authentication is not configured; verification was not sent");
return Optional.empty();
}
JSONObject requestBody = new JSONObject();
requestBody.put("api_key", apiKey);
requestBody.put("api_secret", apiSecret);
Request request = new Request.Builder()
.url(verifyAppAuthUrl)
.header(TenantInternalApiKey.HEADER, configuredInternalKey)
.post(RequestBody.create(requestBody.toJSONString(), JSON_MEDIA_TYPE))
.build();
try (Response response = httpClient.newCall(request).execute()) {
if (!response.isSuccessful()) {
log.warn("tenant verify app auth request failed, status={}", response.code());
return Optional.empty();
}View on GitHub (pinned to 5e758547a8)