OrchardCMS/OrchardCore · error · InvalidOperationException
The 'UnpublishContentTask' can't unpublish the content item…
Error message
The 'UnpublishContentTask' can't unpublish the content item as it is executed inline from a starting 'ContentUnpublishedEvent' of the same content type, which would result in an infinitive loop.
What it means
This guard prevents an infinite republish/unpublish loop: when UnpublishContentTask runs inline (same request) as the starting ContentUnpublishedEvent of the same content type, unpublishing again would re-trigger the same workflow endlessly. The library throws InvalidOperationException to break the cycle.
Solutions
- Use a different starting event triggered earlier in the lifecycle (e.g. ContentDraftSavedEvent) or a non-starting event.
- Restrict the event's content type filter so it does not match the type the task unpublishes.
- Call UnpublishAsync on a different content item type, or restructure using a separate workflow invocation that is not inline.
- Use a LoopBack/condition to prevent re-entry on the same content item.
Example fix
// before Start: ContentUnpublishedEvent (ContentType: Article) -> UnpublishContentTask (same Article item) // after Start: ContentUnpublishedEvent (ContentType: Article) -> Condition (ItemId != source) -> UnpublishContentTask
Defensive patterns
Strategy: validation
Validate before calling
if (inlineEvent.IsStart && inlineEvent.ContentType == targetItem.ContentType && inlineEvent.Name == nameof(ContentUnpublishedEvent))
throw new InvalidOperationException("Refusing to unpublish: would re-enter the starting ContentUnpublishedEvent 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 unpublish loop prevented.");
} Prevention
- Never start a workflow on ContentUnpublishedEvent and unpublish the same content type inline.
- Add an event filter or item-ID condition to break re-entrancy.
- Model cascading unpublishes as separate workflow executions.
- Understand inline vs. queued event execution when designing workflows.
When it happens
Trigger: Workflow started by a ContentUnpublishedEvent (IsStart) whose content type equals the content item being unpublished, executing inline in the same unpublish operation.
Common situations: Developer builds a workflow that reacts to 'Content Unpublished' and itself calls Unpublish on items of the same type (e.g. cascading cleanup over the same type).
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 'UpdateContentTask' can't update the content item as it…
- 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/8ac8db8dcaf99f2e.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore.Modules/OrchardCore.Contents/Workflows/Activities/UnpublishContentTask.cs:53
{
return Outcome("Noop");
}
var contentItem = await ContentManager.GetAsync(content.ContentItem.ContentItemId, VersionOptions.Latest);
if (contentItem == null)
{
if (content is ContentItemIdExpressionResult)
{
throw new InvalidOperationException($"The '{nameof(UnpublishContentTask)}' failed to retrieve the content item.");
}
contentItem = content.ContentItem;
}
if (InlineEvent.IsStart && InlineEvent.ContentType == contentItem.ContentType && InlineEvent.Name == nameof(ContentUnpublishedEvent))
{
throw new InvalidOperationException($"The '{nameof(UnpublishContentTask)}' can't unpublish the content item as it is executed inline from a starting '{nameof(ContentUnpublishedEvent)}' of the same content type, which would result in an infinitive loop.");
}
await ContentManager.UnpublishAsync(contentItem);
return Outcome("Unpublished");
}
}
View on GitHub (pinned to 4306c0717f)