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

  1. Use an event that triggers earlier in the lifecycle, or a different content item as the update target.
  2. Filter the event's content type so it does not include the updated type, or add an ID condition.
  3. Perform the mutation before the save completes (e.g. a content handler) instead of via workflow.
  4. 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

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


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)