iflytek/astron-agent · error · BusinessException
UNAUTHORIZED
UNAUTHORIZED
Error message
BusinessException(ResponseEnum.UNAUTHORIZED)
What it means
UNAUTHORIZED is thrown by getRuntimeModelDetail when the currently authenticated user's uid does not match the authenticatedUid argument passed by the caller. This is an explicit identity-consistency check at the start of the method: the runtime model detail endpoint may only be read by the same user whose authentication context was verified upstream.
Solutions
- Ensure the caller passes the uid taken from the same authenticated security context (UserInfoManagerHandler.get().getUid()), not a client-supplied value.
- Re-authenticate: refresh the token/session so the security context and forwarded uid match.
- Fix the upstream call site to derive authenticatedUid from the current request's auth filter rather than trusting request headers/body.
- Check auth filter/ordering so UserInfoManagerHandler is populated before this method runs.
Example fix
// before
llmInfoVo = modelService.getRuntimeModelDetail(modelId, request.getHeader("uid"), spaceId); // spoofable
// after
String uid = UserInfoManagerHandler.get().getUid();
llmInfoVo = modelService.getRuntimeModelDetail(modelId, uid, spaceId); Defensive patterns
Strategy: type-guard
Validate before calling
if (!Objects.equals(UserInfoManagerHandler.get().getUid(), authenticatedUid)) { throw new SecurityException("uid mismatch before calling getRuntimeModelDetail"); } Type guard
boolean sameIdentity(String authenticatedUid) { UserInfo u = UserInfoManagerHandler.get(); return u != null && Objects.equals(u.getUid(), authenticatedUid); } Try / catch
try { return modelService.getRuntimeModelDetail(modelId, authenticatedUid, spaceId); } catch (BusinessException e) { if ("UNAUTHORIZED".equals(e.getCode())) { forceReauth(); } throw e; } Prevention
- Always derive authenticatedUid from the server-side security context, never from client headers/body.
- Re-read UserInfoManagerHandler after token refresh so contexts stay in sync.
- In inter-service calls, propagate the authenticated uid in a trusted header validated by the auth filter.
- Add an assertion/log when uid mismatch occurs to detect miswired call sites early.
When it happens
Trigger: Calling getRuntimeModelDetail (public entry, e.g. from a chat/runtime controller) where the UserInfoManagerHandler thread-local user differs from the authenticatedUid parameter — e.g. forged/missing auth context, admin-tooling calling with another user's uid, or a token/session mismatch after re-login.
Common situations: Expired or replaced JWT while an old cached uid is passed along; service-to-service calls forwarding a different uid header than the one in the security context; developer tools invoking the method with a hardcoded uid.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/1c784f7b74f871af.
Report an issue: GitHub.
Appendix: source
Thrown at console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/model/ModelService.java:934
String currentUid = userInfo.getUid();
Long currentSpaceId = SpaceInfoUtil.getSpaceId(); // Assuming this gets current space
Model model = findAccessibleModel(modelId, currentUid, currentSpaceId);
if (model == null) {
// Model doesn't exist or user doesn't have access to it
return ApiResult.error(ResponseEnum.MODEL_NOT_EXIST);
}
LLMInfoVo modelVo = buildPublicLLMInfoVoFromModel(model, userInfo);
return ApiResult.success(modelVo);
}
}
public LLMInfoVo getRuntimeModelDetail(Long modelId, String authenticatedUid, Long authorizedSpaceId) {
UserInfo userInfo = UserInfoManagerHandler.get();
if (!Objects.equals(userInfo.getUid(), authenticatedUid)) {
throw new BusinessException(ResponseEnum.UNAUTHORIZED);
}
Model model = findAccessibleModel(modelId, authenticatedUid, authorizedSpaceId);
if (model == null) {
throw new BusinessException(ResponseEnum.MODEL_NOT_EXIST);
}
return buildRuntimeLLMInfoVoFromModel(model, userInfo);
}
private Model findAccessibleModel(Long modelId, String uid, Long spaceId) {
if (spaceId != null && enterpriseSpaceService.checkUserBelongSpace(spaceId, uid) == null) {
return null;
}
LambdaQueryWrapper<Model> wrapper = new LambdaQueryWrapper<Model>()
.eq(Model::getId, modelId)
.eq(Model::getIsDeleted, 0);
if (spaceId != null) {View on GitHub (pinned to 5e758547a8)