{"record":{"id":"d8cb0424a11a8baf","repo":"alibaba/spring-ai-alibaba","slug":"unauthorized-d8cb04","errorCode":"UNAUTHORIZED","errorMessage":"UNAUTHORIZED","messagePattern":"UNAUTHORIZED","errorType":"error_code","errorClass":"BizException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-core/src/main/java/com/alibaba/cloud/ai/studio/core/base/service/impl/WorkflowServiceImpl.java","lineNumber":233,"sourceCode":"\t\t}\n\t\tresponse.setError(error);\n\t\tLogUtils.monitor(context, \"WorkflowService\", \"handleThrowable\", context.getStartTime(), error.getCode(), null,\n\t\t\t\tresponse, err);\n\t\treturn Mono.just(response);\n\t}\n\n\tprivate void checkAndInitContext(WorkflowContext workflowContext, WorkflowRequest request) {\n\t\tLong start = System.currentTimeMillis();\n\t\tRequestContext context = RequestContextHolder.getRequestContext();\n\t\ttry {\n\t\t\t// check input params\n\t\t\tif (Objects.isNull(request)) {\n\t\t\t\tthrow new BizException(ErrorCode.MISSING_PARAMS.toError(\"request\"));\n\t\t\t}\n\n\t\t\tString uid = context.getAccountId();\n\t\t\tif (Objects.isNull(uid)) {\n\t\t\t\tthrow new BizException(ErrorCode.UNAUTHORIZED.toError());\n\t\t\t}\n\n\t\t\tString appId = request.getAppId();\n\t\t\tif (StringUtils.isBlank(appId)) {\n\t\t\t\tthrow new BizException(ErrorCode.MISSING_PARAMS.toError(\"appId\"));\n\t\t\t}\n\n\t\t\t// if (CollectionUtils.isEmpty(request.getMessages())) {\n\t\t\t// throw new BizException(ErrorCode.MISSING_PARAMS.toError(\"messages\"));\n\t\t\t// }\n\n\t\t\tif (Objects.isNull(context.getWorkspaceId())) {\n\t\t\t\tthrow new BizException(ErrorCode.MISSING_PARAMS.toError(\"workspace_id\"));\n\t\t\t}\n\n\t\t\t// get app config\n\t\t\tApplication app = appService.getApp(appId);\n\t\t\tif (app == null) {","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-core/src/main/java/com/alibaba/cloud/ai/studio/core/base/service/impl/WorkflowServiceImpl.java#L215-L251","documentation":"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.","triggerScenarios":"Calling WorkflowService.streamCall without an authenticated session — no auth token, expired token, or an auth filter/interceptor that failed to populate RequestContextHolder.","commonSituations":"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.","solutions":["Authenticate the request (valid token/API key) so the auth filter populates RequestContext.accountId.","Check the auth interceptor/filter is registered and applied to the workflow endpoint path.","Refresh an expired token and retry.","In tests, set up RequestContextHolder with a test RequestContext containing an account id."],"exampleFix":"// before\n// request hits streamCall with no auth header -> UNAUTHORIZED\n// after\nhttp.post(\"/workflow/stream\")\n    .header(\"Authorization\", \"Bearer \" + validToken)\n    .body(workflowRequest);","handlingStrategy":"validation","validationCode":"RequestContext ctx = RequestContextHolder.getRequestContext();\nif (ctx == null || ctx.getAccountId() == null) { throw new AccessDeniedException(\"User not authenticated\"); }","typeGuard":null,"tryCatchPattern":"try { workflowService.streamCall(ctx, request); } catch (BizException e) { if (\"UNAUTHORIZED\".equals(e.getCode())) { /* trigger re-auth / return 401 */ } }","preventionTips":["Attach valid auth credentials to every workflow API call","Ensure the auth filter covers the workflow endpoint paths","Handle token refresh before token expiry","Seed RequestContextHolder properly in tests"],"tags":["auth","unauthorized","workflow","request-context"],"backgroundTag":"authentication-required","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}