alibaba/spring-ai-alibaba · warning · ResponseStatusException
Thread already exists:
Error message
Thread already exists:
What it means
GraphThreadController.createThreadWithId rejects client-supplied thread IDs that already exist for the given graph and user. It first runs findThreadOrThrow as an existence probe; if the thread IS found, it throws a 400 BAD_REQUEST ResponseStatusException. This enforces thread IDs as client-chosen unique keys per (graph, user) pair.
Source
Thrown at spring-ai-alibaba-studio/src/main/java/com/alibaba/cloud/ai/agent/studio/controller/GraphThreadController.java:139
}
return response.threads().stream()
.filter(s -> !s.threadId().startsWith(EVAL_SESSION_ID_PREFIX))
.collect(toList());
}
@PostMapping("/graphs/{graphName}/users/{userId}/threads/{threadId}")
public Thread createThreadWithId(
@PathVariable String graphName,
@PathVariable String userId,
@PathVariable String threadId,
@RequestBody(required = false) Map<String, Object> state) {
validateGraphExists(graphName);
String appName = toAppName(graphName);
try {
findThreadOrThrow(graphName, userId, threadId);
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Thread already exists: " + threadId);
}
catch (ResponseStatusException e) {
if (e.getStatusCode() != HttpStatus.NOT_FOUND) {
throw e;
}
}
Map<String, Object> initialState = (state != null) ? state : Collections.emptyMap();
Thread createdThread = threadService
.createThread(appName, userId, new ConcurrentHashMap<>(initialState), threadId)
.block();
if (createdThread == null) {
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Failed to create thread");
}
return createdThread;
}
View on GitHub (pinned to f82da0b50f)
Solutions
- Check existence first with GET /graphs/{graphName}/users/{userId}/threads/{threadId} and reuse or delete the existing thread
- Use the ID-less creation endpoint POST /graphs/{graphName}/users/{userId}/threads and let the service generate a unique threadId
- Generate a unique threadId client-side (e.g. UUID) instead of a fixed value
- If the existing thread is stale, DELETE it first, then recreate with the same ID
- Catch the 400 ResponseStatusException in your client and treat it as idempotent success if the thread content is acceptable
Example fix
// before POST /graphs/agent/users/u1/threads/session-1 // 400 Thread already exists // after String threadId = UUID.randomUUID().toString(); POST /graphs/agent/users/u1/threads/" + threadId
Defensive patterns
Strategy: validation
Validate before calling
// check existence before creating
try {
restTemplate.getForObject("/graphs/{g}/users/{u}/threads/{t}", Void.class, graph, user, threadId);
return; // already exists
} catch (HttpClientErrorException.NotFound ignored) { }
// safe to create Try / catch
try { create(...) } catch (HttpStatusCodeException e) { if (e.getStatusCode() == HttpStatus.BAD_REQUEST) { /* reuse existing thread */ } else throw e; } Prevention
- Prefer generated-ID endpoints over client-chosen IDs
- Use UUIDs for client-supplied thread IDs
- Make creation retries idempotent by GETting the thread on 400
- Clean up fixed-ID test threads between runs
When it happens
Trigger: POST to /graphs/{graphName}/users/{userId}/threads/{threadId} (PUT-style create) with a threadId that was already created previously for the same graph and user; retrying a successful creation with the same ID; two concurrent creations of the same ID.
Common situations: Client retries after a network timeout when the first request actually succeeded; a UI generating deterministic thread IDs from session names; scripts re-running a setup step that creates threads with fixed IDs.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- Thread already exists:
- Failed to create thread
- Thread not found: appName=%s, userId=%s, threadId=%s
- Thread found but belongs to a different app/user.
- Failed to create thread (null result)
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/538cb1271068ac1a.
Report an issue: GitHub.