alibaba/spring-ai-alibaba · error · BizException

UNAUTHORIZED

UNAUTHORIZED

Error message

UNAUTHORIZED

What it means

UNAUTHORIZED is thrown by checkAndInitContext when the RequestContext has no account id (RequestContextHolder.getRequestContext().getAccountId() is null), meaning the caller is not authenticated. Workflow streaming requires a resolved user identity before proceeding.

Source

Thrown at spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-core/src/main/java/com/alibaba/cloud/ai/studio/core/base/service/impl/WorkflowServiceImpl.java:233

		}
		response.setError(error);
		LogUtils.monitor(context, "WorkflowService", "handleThrowable", context.getStartTime(), error.getCode(), null,
				response, err);
		return Mono.just(response);
	}

	private void checkAndInitContext(WorkflowContext workflowContext, WorkflowRequest request) {
		Long start = System.currentTimeMillis();
		RequestContext context = RequestContextHolder.getRequestContext();
		try {
			// check input params
			if (Objects.isNull(request)) {
				throw new BizException(ErrorCode.MISSING_PARAMS.toError("request"));
			}

			String uid = context.getAccountId();
			if (Objects.isNull(uid)) {
				throw new BizException(ErrorCode.UNAUTHORIZED.toError());
			}

			String appId = request.getAppId();
			if (StringUtils.isBlank(appId)) {
				throw new BizException(ErrorCode.MISSING_PARAMS.toError("appId"));
			}

			// if (CollectionUtils.isEmpty(request.getMessages())) {
			// throw new BizException(ErrorCode.MISSING_PARAMS.toError("messages"));
			// }

			if (Objects.isNull(context.getWorkspaceId())) {
				throw new BizException(ErrorCode.MISSING_PARAMS.toError("workspace_id"));
			}

			// get app config
			Application app = appService.getApp(appId);
			if (app == null) {

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Authenticate the request (valid token/API key) so the auth filter populates RequestContext.accountId.
  2. Check the auth interceptor/filter is registered and applied to the workflow endpoint path.
  3. Refresh an expired token and retry.
  4. In tests, set up RequestContextHolder with a test RequestContext containing an account id.

Example fix

// before
// request hits streamCall with no auth header -> UNAUTHORIZED
// after
http.post("/workflow/stream")
    .header("Authorization", "Bearer " + validToken)
    .body(workflowRequest);
Defensive patterns

Strategy: validation

Validate before calling

RequestContext ctx = RequestContextHolder.getRequestContext();
if (ctx == null || ctx.getAccountId() == null) { throw new AccessDeniedException("User not authenticated"); }

Try / catch

try { workflowService.streamCall(ctx, request); } catch (BizException e) { if ("UNAUTHORIZED".equals(e.getCode())) { /* trigger re-auth / return 401 */ } }

Prevention

When it happens

Trigger: Calling WorkflowService.streamCall without an authenticated session — no auth token, expired token, or an auth filter/interceptor that failed to populate RequestContextHolder.

Common situations: Calling workflow APIs directly without login; API key/token not forwarded through a gateway; session expired mid-use; tests bypassing the auth filter so RequestContextHolder is empty.

Understand the failure class

Related errors


AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09). Data as JSON: /api/errors/d8cb0424a11a8baf. Report an issue: GitHub.