Issue Description
Deleting certain text-heavy emails leaves an UnindexDocument task that can never succeed on FoundationDB. Every attempt fails with Transaction exceeds byte limit (code 2101). Because UnindexDocument uses perpetual_retry_time, the task is retried forever (every 6 h at most), on every node of the cluster. We had six such tasks for one account, with 72 to 110 attempts since mid-September.
SearchStore::unindex (crates/store/src/search/index.rs, around line 160–182 in v0.16.20) loads the document’s TermIndex and writes all of its deletions in a single batch:
let mut batch = BatchBuilder::new();
term_index.delete_index(&mut batch, index, SearchIndexId::Account { account_id, document_id });
self.write(batch.build_all()).await?;
For a text-heavy email the clears add up to more than FoundationDB’s 10 MB transaction limit. #2567 on GitHub fixed the same limit on the indexing path, so such a document can be indexed but not removed again. The code is unchanged in v0.16.26.
A secondary effect: unindex returns on the first failing document, and SearchIndexTask::index then marks every delete in the same batch as failed. Other deletions batched together with the large one are held back too.
Expected Behavior
The term deletions are split into several transactions, e.g. with commit_point() / is_large_batch() the same way the indexing path does after #2567, or the document’s term keys are cleared with a range delete if the key layout allows it. The UnindexDocument task then succeeds.
Actual Behavior
The UnindexDocument task fails with FoundationDB error 2101 on every attempt and stays in Retry indefinitely; attemptNumber keeps increasing (74 after 17 days). Each retry logs a store.foundationdb-error on every node, which in our case fired a “FoundationDB errors” alert four times a day. The orphaned term index of the deleted email stays in the store.
Reproduction Steps
- Use FoundationDB as data store with the internal search engine.
- Deliver an email with a very large text body (or text attachment) so that its term index exceeds ~10 MB of keys, and let it be indexed.
- Delete the email and let it be purged.
- The
UnindexDocumenttask fails with code 2101 and stays inRetryindefinitely (x:Task/getshowsattemptNumberincreasing).
Relevant Log Output
ERROR FoundationDB error (store.foundationdb-error) reason = "Transaction exceeds byte limit", code = 2101, causedBy = "crates/store/src/search/index.rs:182", causedBy = "crates/services/src/task_manager/index.rs:308", details = "Failed to delete documents from index", collection = "email"
Task as returned by x:Task/get:
{
"@type": "UnindexDocument",
"documentType": "email",
"status": {
"@type": "Retry",
"attemptNumber": 74,
"createdAt": "2026-09-25T04:12:55Z",
"failureReason": "Failed to delete documents from index"
}
}
Stalwart Version
v0.16.x
Installation Method
Binary (Linux)
Database Backend
FoundationDB
Blob Storage
S3-compatible
Search Engine
Internal
Directory Backend
Internal
Additional Context
Running v0.16.20 (official release binary in our own container image) on Kubernetes with 2 Stalwart nodes, FoundationDB 7.4.6. The code path is unchanged in v0.16.26. As a workaround we destroyed the stuck tasks via x:Task/set; the orphaned index entries do not show up in search results because Email/query masks hits with the existing messages.
I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.
on
I have searched this support forum (open and closed topics) and confirm this is not a duplicate.
on
I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.
on