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 starting 'ContentUpdatedEvent' of the same content type, which would result in an infinitive loop.
What it means
Loop guard for ContentUpdatedEvent: when UpdateContentTask runs inline from a starting ContentUpdatedEvent whose content type matches the target item, the update re-fires the event and loops forever. InvalidOperationException aborts execution to prevent the infinite cycle.
Solutions
- Start from an earlier event (e.g. ContentDraftSavedEvent) or a non-starting variant.
- Change the event's content type filter so it excludes the updated type.
- Update items of a different content type than the trigger.
- Restructure the mutation in a content handler before the event fires, or invoke a separate workflow execution.
Example fix
// before Start: ContentUpdatedEvent (ContentType: Page) -> UpdateContentTask (Page item, Publish) // after Start: ContentDraftSavedEvent (ContentType: Page) -> UpdateContentTask (Page item)
Defensive patterns
Strategy: validation
Validate before calling
if (!sameItemInline && inlineEvent.IsStart && inlineEvent.ContentType == targetItem.ContentType && inlineEvent.Name == nameof(ContentUpdatedEvent))
throw new InvalidOperationException("UpdateContentTask would re-enter the starting ContentUpdatedEvent of the same type."); Try / catch
try { await task.ExecuteAsync(workflowContext, activityContext); }
catch (InvalidOperationException ex) when (ex.Message.Contains("infinitive loop"))
{
logger.LogWarning(ex, "Inline update loop prevented for ContentUpdatedEvent.");
} Prevention
- Never start a workflow on ContentUpdatedEvent and update the same content type inline.
- Add a content-type or item-ID filter to break re-entrancy.
- Use earlier-lifecycle events (ContentDraftSavedEvent) for same-type updates.
- Move same-item mutations into content handlers where possible.
When it happens
Trigger: !inlineEventOfSameContentItemId && InlineEvent.IsStart && InlineEvent.ContentType == contentItem.ContentType && InlineEvent.Name == 'ContentUpdatedEvent'.
Common situations: Workflow started on 'Content Updated' for type X that itself updates items of type X; each update re-triggers the workflow.
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/1a1d10f6123b03d8.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore.Modules/OrchardCore.Contents/Workflows/Activities/UpdateContentTask.cs:112
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.");
}
if (!inlineEventOfSameContentItemId && InlineEvent.IsStart && InlineEvent.ContentType == contentItem.ContentType)
{
if (InlineEvent.Name == nameof(ContentUpdatedEvent))
{
throw new InvalidOperationException($"The '{nameof(UpdateContentTask)}' can't update the content item as it is executed inline from a starting '{nameof(ContentUpdatedEvent)}' of the same content type, which would result in an infinitive loop.");
}
if (Publish && InlineEvent.Name == nameof(ContentPublishedEvent))
{
throw new InvalidOperationException($"The '{nameof(UpdateContentTask)}' can't publish the content item as it is executed inline from a starting '{nameof(ContentPublishedEvent)}' of the same content type, which would result in an infinitive loop.");
}
if (!Publish && InlineEvent.Name == nameof(ContentDraftSavedEvent))
{
throw new InvalidOperationException($"The '{nameof(UpdateContentTask)}' can't update the content item as it is executed inline from a starting '{nameof(ContentDraftSavedEvent)}' of the same content type, which would result in an infinitive loop.");
}
}
if (!string.IsNullOrWhiteSpace(ContentProperties.Expression))
{
var contentProperties = await _expressionEvaluator.EvaluateAsync(ContentProperties, workflowContext, _javaScriptEncoder);
contentItem.Merge(JsonNode.Parse(contentProperties), new JsonMergeSettings { MergeArrayHandling = MergeArrayHandling.Replace });
}View on GitHub (pinned to 4306c0717f)