iflytek/astron-agent · error · BusinessException

UNAUTHORIZED

UNAUTHORIZED

Error message

UNAUTHORIZED

What it means

applyCurrentArtifactScope throws UNAUTHORIZED when UserInfoManagerHandler.getUserId() returns a blank user ID, meaning no authenticated user context is present for the request. Every artifact query (getScopedArtifact, scopeQuery) runs through this scoping, so any artifact read/list/delete without a valid session/user is rejected before the DB query is even built.

Solutions

  1. Authenticate first and retry the request with a valid session token/Authorization header
  2. Check gateway/filter configuration so the auth header reaches UserInfoManagerHandler (not stripped by a proxy)
  3. For background jobs, propagate or impersonate a system user context rather than calling the scoped service directly
  4. Refresh the expired token in the frontend and replay the request

Example fix

// before: unauthenticated call
curl http://console/api/workflow/artifact/123
// after
curl -H "Authorization: Bearer $TOKEN" \
     http://console/api/workflow/artifact/123
Defensive patterns

Strategy: validation

Validate before calling

// Ensure a session/token exists before calling artifact APIs
String token = sessionStore.currentToken();
if (token == null || token.isBlank())
    throw new AuthRequiredException("Login required before artifact operations");

Try / catch

try {
    artifactApi.listArtifacts(workflowId);
} catch (BusinessException e) {
    if ("UNAUTHORIZED".equals(e.getCode())) {
        await reauthenticate(); // refresh token then replay
        return artifactApi.listArtifacts(workflowId);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling artifact APIs without a valid login session/token; expired JWT stripped by the gateway so the user context is empty; internal/scheduled jobs calling the service outside a request-scoped security context; missing auth header on direct service calls.

Common situations: Token expiry during long UI sessions; requests proxied to the backend without the auth header; testing the API with curl and no Authorization header; background threads invoking service methods without propagating the user context.

Understand the failure class

Related errors


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

Appendix: source

Thrown at console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/workflow/WorkflowArtifactService.java:390

        if (artifact == null) {
            throw new BusinessException(ResponseEnum.DATA_NOT_EXIST);
        }
        return artifact;
    }

    private LambdaQueryWrapper<WorkflowArtifact> scopeQuery(Long workflowId) {
        LambdaQueryWrapper<WorkflowArtifact> wrapper = Wrappers.lambdaQuery(WorkflowArtifact.class)
                .eq(WorkflowArtifact::getWorkflowId, workflowId)
                .eq(WorkflowArtifact::getDeleted, Boolean.FALSE);
        applyCurrentArtifactScope(wrapper);
        return wrapper;
    }

    private void applyCurrentArtifactScope(LambdaQueryWrapper<WorkflowArtifact> wrapper) {
        String currentUid = UserInfoManagerHandler.getUserId();
        Long spaceId = SpaceInfoUtil.getSpaceId();
        if (StringUtils.isBlank(currentUid)) {
            throw new BusinessException(ResponseEnum.UNAUTHORIZED);
        }
        if (spaceId != null) {
            if (spaceUserService.getRole(spaceId, currentUid) == null) {
                throw new BusinessException(ResponseEnum.INSUFFICIENT_PERMISSIONS);
            }
            wrapper.eq(WorkflowArtifact::getSpaceId, spaceId);
        } else {
            wrapper.isNull(WorkflowArtifact::getSpaceId)
                    .eq(WorkflowArtifact::getUid, currentUid);
        }
    }

    private void assertWorkflowVisible(Long workflowId) {
        Workflow workflow = workflowMapper.selectOne(Wrappers.lambdaQuery(Workflow.class)
                .eq(Workflow::getId, workflowId)
                .eq(Workflow::getDeleted, Boolean.FALSE)
                .last("limit 1"));
        if (workflow == null) {

View on GitHub (pinned to 5e758547a8)