{"record":{"id":"3c07a0d701d66c77","repo":"alibaba/spring-ai-alibaba","slug":"threadid-cannot-be-null-or-empty","errorCode":null,"errorMessage":"threadId cannot be null or empty","messagePattern":"threadId cannot be null or empty","errorType":"http","errorClass":"ResponseStatusException","httpStatus":400,"severity":"error","filePath":"spring-ai-alibaba-studio/src/main/java/com/alibaba/cloud/ai/agent/studio/controller/ExecutionController.java","lineNumber":171,"sourceCode":"\t * @return A Flux that will stream events to the client in standard SSE format.\n\t */\n\t@PostMapping(value = \"/run_sse\", produces = MediaType.TEXT_EVENT_STREAM_VALUE)\n\tpublic Flux<ServerSentEvent<String>> agentRunSse(@RequestBody AgentRunRequest request) {\n\t\tif (request.appName == null || request.appName.trim().isEmpty()) {\n\t\t\tlog.warn(\n\t\t\t\t\t\"appName cannot be null or empty in SSE request for appName: {}, session: {}\",\n\t\t\t\t\trequest.appName,\n\t\t\t\t\trequest.threadId);\n\t\t\treturn Flux.error(\n\t\t\t\t\tnew ResponseStatusException(HttpStatus.BAD_REQUEST, \"appName cannot be null or empty\"));\n\t\t}\n\t\tif (request.threadId == null || request.threadId.trim().isEmpty()) {\n\t\t\tlog.warn(\n\t\t\t\t\t\"threadId cannot be null or empty in SSE request for appName: {}, session: {}\",\n\t\t\t\t\trequest.appName,\n\t\t\t\t\trequest.threadId);\n\t\t\treturn Flux.error(\n\t\t\t\t\tnew ResponseStatusException(HttpStatus.BAD_REQUEST, \"threadId cannot be null or empty\"));\n\t\t}\n\n\t\ttry {\n\t\t\tAgent agent = agentLoader.loadAgent(request.appName);\n\t\t\tRunnableConfig runnableConfig = RunnableConfig.builder()\n\t\t\t\t\t.threadId(request.threadId)\n\t\t\t\t\t.addMetadata(\"user_id\", request.userId)\n\t\t\t\t\t.build();\n\n\t\t\treturn executeAgent(request.newMessage.toUserMessage(), agent, runnableConfig);\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tlog.error(\"Error during agent run for session {}\", request.threadId, e);\n\t\t\treturn Flux.error(new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, \"Agent run failed\", e));\n\t\t}\n\t}\n\n\t@PostMapping(value = \"/resume_sse\", produces = MediaType.TEXT_EVENT_STREAM_VALUE)","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-studio/src/main/java/com/alibaba/cloud/ai/agent/studio/controller/ExecutionController.java#L153-L189","documentation":"The SSE run endpoint rejects requests whose threadId is null or blank. Spring AI Alibaba's ExecutionController requires a threadId to identify the conversation/checkpoint stream, so it returns a 400 ResponseStatusException wrapped in a Flux error before any agent loading happens.","triggerScenarios":"POSTing to /execution/run_sse with a JSON body whose threadId field is absent, null, or whitespace-only.","commonSituations":"Client SDKs omitting threadId when starting a run; frontend state not yet initialized before opening the SSE stream; serialized request objects dropping empty strings; API version changes renaming the field.","solutions":["Set a non-empty threadId in the AgentRunRequest body before calling the endpoint","Generate a threadId client-side (e.g. UUID) when starting a new conversation","Validate the request payload on the client before opening the SSE connection"],"exampleFix":"// before\nPOST /run_sse {\"appName\":\"chatbot\"}\n// after\nPOST /run_sse {\"appName\":\"chatbot\",\"threadId\":\"a1b2c3\"}","handlingStrategy":"validation","validationCode":"if (req.threadId == null || req.threadId.trim().isEmpty()) { throw new IllegalArgumentException(\"threadId required\"); }","typeGuard":"boolean hasThreadId(AgentRunRequest r) { return r != null && r.threadId() != null && !r.threadId().trim().isEmpty(); }","tryCatchPattern":"try { flux.subscribe(...) } catch (ResponseStatusException e) { if (e.getStatusCode() == HttpStatus.BAD_REQUEST) { /* fix request fields */ } }","preventionTips":["Always set threadId before calling /run_sse","Generate a UUID threadId per conversation on the client","Validate required request fields before opening SSE streams"],"tags":["http","validation","sse"],"backgroundTag":"empty-required-field","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"}