OrchardCMS/OrchardCore · error · InvalidOperationException
The 'UpdateContentTask' can't update the content item as it…
Error message
The 'UpdateContentTask' can't update the content item as it is executed inline from a 'ContentDraftSavedEvent' of the same content item, please use an event that is triggered earlier.
What it means
Companion guard to the published-event case: when the task runs inline within a ContentDraftSavedEvent of the same content item, saving a draft update would re-trigger the same event in an endless loop. InvalidOperationException is thrown to break the cycle.
Solutions
- Use an event that triggers earlier in the lifecycle, or a different content item as the update target.
- Filter the event's content type so it does not include the updated type, or add an ID condition.
- Perform the mutation before the save completes (e.g. a content handler) instead of via workflow.
- Trigger a separate workflow execution rather than running inline.
Example fix
// before Workflow start: ContentDraftSavedEvent -> UpdateContentTask (same item) // after Workflow start: ContentUpdatedEvent (non-starting) or update different item
Defensive patterns
Strategy: validation
Validate before calling
if (inlineEvent?.Name == nameof(ContentDraftSavedEvent) && string.Equals(inlineEvent.ContentItemId, targetId, StringComparison.OrdinalIgnoreCase))
throw new InvalidOperationException("UpdateContentTask would re-enter ContentDraftSavedEvent for the same item."); Try / catch
try { await task.ExecuteAsync(workflowContext, activityContext); }
catch (InvalidOperationException ex) when (ex.Message.Contains("ContentDraftSavedEvent"))
{
logger.LogWarning(ex, "Inline update-after-draft-save loop prevented.");
} Prevention
- Avoid UpdateContentTask (same item) directly after ContentDraftSavedEvent.
- Choose earlier-lifecycle events or update a different item.
- Add an ID-equality condition as a loop breaker.
- Use content handlers for pre-save mutations instead of workflows.
When it happens
Trigger: InlineEvent.Name == 'ContentDraftSavedEvent' and InlineEvent.ContentItemId equals the activity's evaluated contentItemId.
Common situations: Workflow: ContentDraftSavedEvent -> UpdateContentTask targeting the same item; each draft save re-fires the event.
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
- The 'UnpublishContentTask' can't unpublish the content item…
- The 'UpdateContentTask' can't update the content item as it…
- The 'UpdateContentTask' can't update the content item as it…
- The 'UpdateContentTask' can't publish the content item as…
- The 'UpdateContentTask' can't update the content item as it…
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/7803c0ade9967689.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore.Modules/OrchardCore.Contents/Workflows/Activities/UpdateContentTask.cs:88
=> Outcome(S["Done"], S["Failed"]);
public override async Task<ActivityExecutionResult> ExecuteAsync(WorkflowExecutionContext workflowContext, ActivityContext activityContext)
{
var contentItemId = (await GetContentItemIdAsync(workflowContext))
?? throw new InvalidOperationException($"The {nameof(UpdateContentTask)} failed to evaluate the 'ContentItemId'.");
var inlineEventOfSameContentItemId = string.Equals(InlineEvent.ContentItemId, contentItemId, StringComparison.OrdinalIgnoreCase);
if (inlineEventOfSameContentItemId)
{
if (InlineEvent.Name == nameof(ContentPublishedEvent))
{
throw new InvalidOperationException($"The '{nameof(UpdateContentTask)}' can't update the content item as it is executed inline from a '{nameof(ContentPublishedEvent)}' of the same content item, please use an event that is triggered earlier.");
}
if (InlineEvent.Name == nameof(ContentDraftSavedEvent))
{
throw new InvalidOperationException($"The '{nameof(UpdateContentTask)}' can't update the content item as it is executed inline from a '{nameof(ContentDraftSavedEvent)}' of the same content item, please use an event that is triggered earlier.");
}
}
ContentItem contentItem = null;
if (!inlineEventOfSameContentItemId)
{
contentItem = await ContentManager.GetAsync(contentItemId, VersionOptions.DraftRequired);
}
else
{
contentItem = workflowContext.Input.GetValue<IContent>(ContentEventConstants.ContentItemInputKey)?.ContentItem;
}
if (contentItem == null)
{
throw new InvalidOperationException($"The '{nameof(UpdateContentTask)}' failed to retrieve the content item.");
}View on GitHub (pinned to 4306c0717f)