OrchardCMS/OrchardCore · error · DocumentStoreCommitException
The ' ' could not be persisted and cached as it has been…
Error message
The '{typeof(T).Name}' could not be persisted and cached as it has been changed by another process. What it means
DocumentStore.UpdateAsync wraps the persistence + cache update of a document. If the transaction commits fail because the document was concurrently modified by another process/shell instance (YesSql optimistic concurrency), AfterCommitFailure rethrows as DocumentStoreCommitException with this message. It means the in-memory document version is stale relative to what is stored.
Solutions
- Reload the latest document and re-apply your changes, then retry UpdateAsync (last-write-wins with a fresh read).
- Reduce the write window: load the document as late as possible and save immediately.
- For shared singleton documents, serialize writes through a single writer or use distributed locking (e.g., a database-based lock) before updating.
- Inspect the inner exception to confirm it is YesSql concurrency (version mismatch) rather than a connection failure.
Example fix
// before
var settings = await session.Query<SiteSettings>().FirstOrDefaultAsync();
settings.PageSize = 50;
await session.SaveAsync(settings);
// after (retry on stale document)
try
{
settings.PageSize = 50;
await session.SaveAsync(settings);
}
catch (DocumentStoreCommitException)
{
session = await sessionFactory.CreateScopeAsync();
settings = await session.Query<SiteSettings>().FirstOrDefaultAsync();
settings.PageSize = 50;
await session.SaveAsync(settings);
} Defensive patterns
Strategy: retry
Try / catch
catch (DocumentStoreCommitException ex) when (ex.InnerException is ConcurrencyException) { // reload document and retry up to N times } Prevention
- Minimize the time between loading and saving shared documents
- Avoid holding a loaded document across long-running operations or user input
- Use locking or a single writer for hot singleton documents in multi-instance deployments
When it happens
Trigger: Calling ISession/documentStore UpdateAsync for a document whose stored version was changed by another process between load and commit — the YesSql concurrency check fails during commit.
Common situations: Multiple app instances or background jobs writing the same singleton document (e.g., SiteSettings, recipe state) simultaneously; a long-running request holding a document while another request saves it first; load-balanced deployments sharing one database.
Related errors
- The token was concurrently updated and cannot be persisted…
- Invalid serial number for shell descriptor
- Unable to reload the tenant
- Can't resolve a scope on tenant
- Failed to acquire a lock before activating the tenant
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/1606ad88a549086b.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore/OrchardCore.Data.YesSql/Documents/DocumentStore.cs:75
return (true, document);
}
return (true, await (factoryAsync?.Invoke() ?? Task.FromResult((T)null)) ?? new T());
}
/// <inheritdoc />
public async Task UpdateAsync<T>(T document, Func<T, Task> updateCache, bool checkConcurrency = false)
{
await _session.SaveAsync(document, checkConcurrency);
AfterCommitSuccess<T>(() =>
{
return updateCache(document);
});
AfterCommitFailure<T>(exception =>
{
throw new DocumentStoreCommitException(
$"The '{typeof(T).Name}' could not be persisted and cached as it has been changed by another process.",
exception);
});
}
/// <inheritdoc />
public async Task CancelAsync()
{
_canceled = true;
if (_session is null)
{
return;
}
await _session.CancelAsync();
}
View on GitHub (pinned to 4306c0717f)