iflytek/astron-agent · error · BusinessException

EXCEED_AUTHORITY

EXCEED_AUTHORITY

Error message

BusinessException(ResponseEnum.EXCEED_AUTHORITY)

What it means

Thrown by checkAndDelete after the model is found, when model.getUid() does not equal the uid resolved from the current session (UserInfoManagerHandler.getUserId()). Only the owner may delete a model; anyone else — even a space admin — receives EXCEED_AUTHORITY.

Solutions

  1. Delete the model as the owning user (log in with or use credentials of model.getUid()).
  2. Have the owner delete it, or add an explicit admin/transfer flow if delegation is required.
  3. Verify the auth context (UserInfoManagerHandler) resolves the expected uid — check token/session mismatch.
  4. Compare stored uid and session uid for format differences (whitespace, case) if ownership looks correct.

Example fix

// before
// deleting with a service account token whose uid != model owner
await deleteModel(modelId);
// after
const model = await getModelDetail(modelId);
if (model.uid !== currentUid) {
  throw new Error(`Only owner ${model.uid} can delete model ${modelId}`);
}
await deleteModel(modelId);
Defensive patterns

Strategy: validation

Validate before calling

Model m = modelService.getById(modelId);
boolean owned = m != null && Objects.equals(m.getUid(), UserInfoManagerHandler.getUserId());

Type guard

if (m == null || m.getUid() == null || !m.getUid().equals(currentUid)) { /* not owner */ }

Try / catch

try { return modelService.checkAndDelete(modelId, request); }
catch (BusinessException e) {
  if (ResponseEnum.EXCEED_AUTHORITY.equals(e.getResponseEnum())) {
    throw new BusinessException(e.getResponseEnum(), "Only the model owner can delete this model");
  }
  throw e;
}

Prevention

When it happens

Trigger: Authenticated user A invokes the delete API for a model created by user B; session/uid header resolves to a different account than the one that created the model (e.g. after switching accounts or service-account tokens).

Common situations: Shared test environments where a teammate tries to delete another's model; API tokens belonging to a different user than the UI session; uid stored with different casing/format so equals() fails.

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.

Related errors


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

Appendix: source

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

        ConfigInfo publicKey =
                configInfoMapper.selectOne(
                        new LambdaQueryWrapper<ConfigInfo>()
                                .eq(ConfigInfo::getCategory, CAT_MODEL_SECRET_KEY)
                                .eq(ConfigInfo::getCode, CODE_PUBLIC_KEY)
                                .eq(ConfigInfo::getIsValid, 1));
        return Optional.ofNullable(publicKey).map(ConfigInfo::getValue).orElse(null);
    }

    @Transactional(rollbackFor = Exception.class)
    public ApiResult checkAndDelete(Long modelId, HttpServletRequest request) {
        String uid = UserInfoManagerHandler.getUserId();
        Model model = this.getById(modelId);
        if (model == null) {
            throw new BusinessException(ResponseEnum.MODEL_NOT_EXIST);
        }
        if (!model.getUid().equals(uid)) {
            log.warn("Unauthorized deletion, uid={}, modelId={}", uid, modelId);
            throw new BusinessException(ResponseEnum.EXCEED_AUTHORITY);
        }

        checkWorkflowReference(uid, model);

        Integer modelCount = sparkBotMapper.checkDomainIsUsage(uid, model.getDomain());
        if (modelCount != null && modelCount > 0) {
            throw new BusinessException(ResponseEnum.MODEL_DELETE_FAILED_APPLY_AGENT);
        }

        boolean result;
        if (Objects.equals(model.getType(), 1)) {
            result = this.removeById(modelId);
        } else {
            result = this.removeById(modelId) && modelHandler.deleteModel(model.getRemark());
        }
        return ApiResult.success(result);
    }

View on GitHub (pinned to 5e758547a8)