alibaba/spring-ai-alibaba · error · IllegalStateException
Thread not found: <threadName>
Error message
Thread not found: <threadName>
What it means
In MongoSaver.release(), after the threadId is known, the saver looks up the thread's metadata document (id = THREAD_META_PREFIX + threadName) inside a transaction. If no such document exists, it aborts the transaction and throws IllegalStateException('Thread not found: <threadName>'). This means the thread was never persisted or has no metadata record in the thread_meta collection.
Source
Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/mongo/MongoSaver.java:466
@Override
public Tag release(RunnableConfig config) throws Exception {
Optional<String> threadNameOpt = config.threadId();
if (!threadNameOpt.isPresent()) {
throw new IllegalArgumentException("threadId is not allow null");
}
String threadName = threadNameOpt.get();
ClientSession clientSession = this.client
.startSession(ClientSessionOptions.builder().defaultTransactionOptions(txnOptions).build());
clientSession.startTransaction();
try {
MongoCollection<Document> threadMetaCollection = database.getCollection(THREAD_META_COLLECTION);
String metaId = THREAD_META_PREFIX + threadName;
Document metaDoc = threadMetaCollection.find(clientSession, new BasicDBObject("_id", metaId)).first();
if (metaDoc == null) {
clientSession.abortTransaction();
throw new IllegalStateException("Thread not found: " + threadName);
}
String threadId = metaDoc.getString(FIELD_THREAD_ID);
if (threadId == null) {
clientSession.abortTransaction();
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)View on GitHub (pinned to f82da0b50f)
Solutions
- Verify the thread exists (e.g. via list() or by querying the thread_meta collection for _id = 'thread_meta:<name>') before releasing
- Point the saver at the same MongoDB database/namespace where the checkpoints were written
- Re-check the threadId string for typos, whitespace, or case differences
- If the metadata was purged, recreate the thread (put a checkpoint) before releasing
Example fix
// before
saver.release(cfg); // throws if thread never saved
// after
if (saver.list(cfg).isEmpty()) {
throw new IllegalStateException("Nothing to release for " + threadId);
}
saver.release(cfg); Defensive patterns
Strategy: validation
Validate before calling
// ensure the thread was persisted before releasing
if (saver.list(config).isEmpty()) {
throw new IllegalStateException("Thread " + threadId + " has no checkpoints; nothing to release");
}
saver.release(config); Try / catch
try {
saver.release(cfg);
} catch (IllegalStateException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Thread not found")) {
log.warn("Thread already gone or never created: {}", threadId);
return;
}
throw e;
} Prevention
- Only release threads that were previously checkpointed via put()
- Confirm the saver's database matches the one that wrote the thread
- Watch for schema/prefix changes across library upgrades
When it happens
Trigger: Calling release(config) with a threadId for which no metadata document exists in the THREAD_META_COLLECTION (e.g. the thread was never put()/checkpointed, the collection was dropped, or the meta id prefix convention changed between versions).
Common situations: Releasing a thread against a fresh/different Mongo database than the one used to create checkpoints; typos or casing mismatches in the thread name; cleanup code running after someone purged collections manually; version upgrades altering _id formats.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- threadId is not allowed to be null
- threadId is not allow null
- Thread is not active or already released: <threadName>
- checkpoints.numRetained must be a number or numeric string,
- Multiple savers configured, but no specific one requested.
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/f6c6c584c817f546.
Report an issue: GitHub.