OrchardCMS/OrchardCore · error · InvalidOperationException

The 'CreateContentTask' can't update the content item as it…

Error message

The 'CreateContentTask' 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

CreateContentTask.ExecuteAsync throws this InvalidOperationException when the workflow was started inline by a ContentUpdatedEvent for the same content type the task would create/update. Because inline workflows run synchronously inside the content event pipeline, creating/updating content of that type would re-trigger the same event, producing an infinite loop. The throw is a deliberate safety guard in Orchard Core Workflows.

Solutions

  1. Change the CreateContentTask's ContentType to a different content type than the one that starts the workflow.
  2. Disable the workflow's InlineEvent delivery (configure the workflow to run non-inline/queued) so the loop guard is not engaged, and add a loop-avoidance condition instead.
  3. Use a different starting event (e.g. ContentCreatedEvent or ContentPublishedEvent) that does not conflict with the task's operation.
  4. Catch InvalidOperationException in custom host code and log/skip the activity run.

Example fix

// before: workflow starts on ContentUpdatedEvent for 'Article', task creates 'Article'
ContentType = "Article";
// after: create a distinct audit content type instead
ContentType = "ArticleAuditEntry";
Defensive patterns

Strategy: validation

Validate before calling

// Before configuring/saving the workflow
bool loops = triggerEvent == "ContentUpdatedEvent"
    && triggerIsStart
    && string.Equals(triggerContentType, taskContentType, StringComparison.OrdinalIgnoreCase);
if (loops) throw new InvalidOperationException("CreateContentTask ContentType must differ from the starting event's content type.");

Try / catch

try { await workflowManager.TriggerEventAsync(nameof(ContentUpdatedEvent), ...); }
catch (InvalidOperationException ex) when (ex.Message.Contains("CreateContentTask") && ex.Message.Contains("infinitive loop"))
{
    logger.LogWarning(ex, "Workflow loop guard triggered; reconfigure the workflow.");
}

Prevention

When it happens

Trigger: A workflow with a starting ContentUpdatedEvent activity (IsStart=true) whose ContentType matches the CreateContentTask's ContentType property, and the task's ContentProperties expression targets the same content type, executed inline (inline event delivery, not the queued/default path).

Common situations: Developer builds a workflow 'when a Page is updated, create/update a related Page' with an inline-starting ContentUpdatedEvent; self-referential content synchronization rules; copying a workflow designed for a different event type onto ContentUpdatedEvent without changing the task's ContentType.

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/5c3ac49026486014. Report an issue: GitHub.

Appendix: source

Thrown at src/OrchardCore.Modules/OrchardCore.Contents/Workflows/Activities/CreateContentTask.cs:73

        get => GetProperty(() => new WorkflowExpression<string>(JConvert.SerializeObject(new { DisplayText = S["Enter a title"].Value }, JOptions.Indented)));
        set => SetProperty(value);
    }

    public override bool CanExecute(WorkflowExecutionContext workflowContext, ActivityContext activityContext)
    {
        return !string.IsNullOrEmpty(ContentType);
    }

    public override IEnumerable<Outcome> GetPossibleOutcomes(WorkflowExecutionContext workflowContext, ActivityContext activityContext)
        => Outcome(S["Done"], S["Failed"]);

    public override async Task<ActivityExecutionResult> ExecuteAsync(WorkflowExecutionContext workflowContext, ActivityContext activityContext)
    {
        if (InlineEvent.IsStart && InlineEvent.ContentType == ContentType)
        {
            if (InlineEvent.Name == nameof(ContentUpdatedEvent))
            {
                throw new InvalidOperationException($"The '{nameof(CreateContentTask)}' 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 (InlineEvent.Name == nameof(ContentCreatedEvent))
            {
                throw new InvalidOperationException($"The '{nameof(CreateContentTask)}' can't create the content item as it is executed inline from a starting '{nameof(ContentCreatedEvent)}' of the same content type, which would result in an infinitive loop.");
            }

            if (Publish && InlineEvent.Name == nameof(ContentPublishedEvent))
            {
                throw new InvalidOperationException($"The '{nameof(CreateContentTask)}' 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(CreateContentTask)}' can't create 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.");
            }
        }

View on GitHub (pinned to 4306c0717f)