alibaba/spring-ai-alibaba · error · IllegalStateException
Thread is not active or already released: <threadName>
Error message
Thread is not active or already released: <threadName>
What it means
During release(), MongoSaver marks the thread as released with a conditional findOneAndUpdate filtered on _id = metaId AND is_released = false. If the update matches nothing (thread already released, or meta vanished between the read and the update), the transaction is aborted and IllegalStateException('Thread is not active or already released: <threadName>') is thrown.
Source
Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/mongo/MongoSaver.java:490
throw new IllegalStateException("Thread not found: " + threadName);
}
// Mark thread as released atomically
// Use findOneAndUpdate with condition to ensure we only release active threads
Document releaseFilter = new Document("_id", metaId)
.append(FIELD_IS_RELEASED, false); // Only release if not already released
Document updatedDoc = threadMetaCollection.findOneAndUpdate(
clientSession,
releaseFilter,
Updates.set(FIELD_IS_RELEASED, true),
new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER)
);
if (updatedDoc == null) {
// Thread was already released or doesn't exist
clientSession.abortTransaction();
throw new IllegalStateException("Thread is not active or already released: " + threadName);
}
// Get checkpoints for Tag (using thread_id)
MongoCollection<Document> checkpointCollection = database.getCollection(CHECKPOINT_COLLECTION);
String checkpointDocId = CHECKPOINT_PREFIX + threadId;
Document checkpointDoc = checkpointCollection.find(clientSession, new BasicDBObject("_id", checkpointDocId))
.first();
Collection<Checkpoint> checkpoints = Collections.emptyList();
if (checkpointDoc != null) {
String checkpointsStr = checkpointDoc.getString(DOCUMENT_CONTENT_KEY);
if (checkpointsStr != null) {
checkpoints = deserializeCheckpoints(checkpointsStr);
}
}
clientSession.commitTransaction();
return new Tag(threadName, checkpoints);View on GitHub (pinned to f82da0b50f)
Solutions
- Treat release as non-idempotent: track released threads in application state and skip already-released ones
- Catch IllegalStateException and, if the message says 'already released', treat it as success in cleanup paths
- Serialize releases per thread (locking or a leader election) if multiple workers may release concurrently
Example fix
// before
saver.release(cfg); // second call throws
// after
try {
saver.release(cfg);
} catch (IllegalStateException e) {
if (!e.getMessage().contains("already released")) throw e;
// already released: treat as success
} Defensive patterns
Strategy: try-catch
Try / catch
try {
saver.release(cfg);
} catch (IllegalStateException e) {
if (e.getMessage() != null && e.getMessage().contains("already released")) {
return; // idempotent success
}
throw e;
} Prevention
- Treat release as one-shot; track released threads in app state
- Avoid releasing the same threadId from multiple workers concurrently
- Design cleanup jobs to tolerate already-released threads
When it happens
Trigger: Calling release(config) twice on the same thread; concurrent release calls racing on the same threadId; a thread that was released in a previous run but is still referenced by application state.
Common situations: Retry logic re-invoking release after a timeout even though the first attempt committed; multiple workers cleaning up the same thread; idempotency assumptions in batch shutdown code.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Thread not found: <threadName>
- Failed to delete experiment
- maxParallelTools must be at least 1
- maxConcurrency must be at least 1, but got:
- threadId is not allowed to be null
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/aa8579d637173681.
Report an issue: GitHub.