{"record":{"id":"b239e6e8f32e2d4a","repo":"OrchardCMS/OrchardCore","slug":"can-t-update-a-cached-object","errorCode":null,"errorMessage":"Can't update a cached object","messagePattern":"Can't update a cached object","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore/OrchardCore.Infrastructure/Documents/DocumentManager.cs","lineNumber":179,"sourceCode":"        if (_isDistributed)\n        {\n            try\n            {\n                _ = await _distributedCache.GetStringAsync(_options.CacheIdKey);\n            }\n            catch\n            {\n                await DocumentStore.CancelAsync();\n\n                _logger.LogError(\"Can't update the '{DocumentName}' if not able to access the distributed cache\", typeof(TDocument).Name);\n\n                throw;\n            }\n        }\n\n        if (_memoryCache.TryGetValue<TDocument>(_options.CacheKey, out var cached) && document == cached)\n        {\n            throw new InvalidOperationException(\"Can't update a cached object\");\n        }\n\n        document.Identifier ??= IdGenerator.GenerateId();\n\n        if (!_isVolatile)\n        {\n            await DocumentStore.UpdateAsync(document, async document =>\n            {\n                // A non volatile document can be invalidated.\n                await InvalidateInternalAsync(document);\n\n                if (afterUpdateAsync != null)\n                {\n                    await afterUpdateAsync(document);\n                }\n            },\n            _options.CheckConcurrency.Value);\n","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore/OrchardCore.Infrastructure/Documents/DocumentManager.cs#L161-L197","documentation":"DocumentManager<TDocument>.UpdateAsync persists a mutated document but first checks whether the instance being saved is the exact same object as the one in the memory cache. Saving the cached instance would corrupt the shared cache, so it throws InvalidOperationException and refuses the update.","triggerScenarios":"Calling UpdateAsync with the same document instance currently stored under the manager's CacheKey — e.g. mutating and re-saving the object obtained from GetAsync without going through GetOrCreateMutableAsync.","commonSituations":"Developer fetches the cached document via GetAsync, mutates it, and calls UpdateAsync on it; custom cache/store setups where identity equality holds between fetched and cached objects.","solutions":["Use GetOrCreateMutableAsync to obtain a mutable copy before editing, then UpdateAsync that copy.","Clone the document before mutating if you must edit a value obtained from GetAsync.","Never mutate documents returned by the read path; treat them as immutable shared instances."],"exampleFix":"// before\nvar doc = await documentManager.GetAsync();\ndoc.Settings.Enabled = true;\nawait documentManager.UpdateAsync(doc); // cached instance\n// after\nvar mutable = await documentManager.GetOrCreateMutableAsync();\nmutable.Settings.Enabled = true;\nawait documentManager.UpdateAsync(mutable);","handlingStrategy":"try-catch","validationCode":"// Ensure the doc is not the cached instance before updating:\n_memoryCache.TryGetValue<TDocument>(cacheKey, out var cached);\nif (ReferenceEquals(doc, cached)) doc = Clone(doc);","typeGuard":"bool IsSafeToUpdate<T>(T doc, T cached) => !ReferenceEquals(doc, cached);","tryCatchPattern":"try { await manager.UpdateAsync(doc); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Can't update a cached object\")) {\n    // re-fetch via GetOrCreateMutableAsync and reapply changes\n}","preventionTips":["Treat documents from GetAsync as immutable","Always use GetOrCreateMutableAsync for read-modify-write flows","Clone before mutating when unsure of instance provenance"],"tags":["documents","caching","immutability","invalid-state-transition"],"backgroundTag":"invalid-state-transition","analyzedSha":"4306c0717fe573f6fca1b4955909ddab6a192807","analyzedAt":"2026-09-13T17:41:05.024Z","contentChangedAt":"2026-09-13T17:41:05.024Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}