{"record":{"id":"5c3ac49026486014","repo":"OrchardCMS/OrchardCore","slug":"the-createcontenttask-can-t-update-the-content-item-as-it-is","errorCode":null,"errorMessage":"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.","messagePattern":"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\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore.Modules/OrchardCore.Contents/Workflows/Activities/CreateContentTask.cs","lineNumber":73,"sourceCode":"        get => GetProperty(() => new WorkflowExpression<string>(JConvert.SerializeObject(new { DisplayText = S[\"Enter a title\"].Value }, JOptions.Indented)));\n        set => SetProperty(value);\n    }\n\n    public override bool CanExecute(WorkflowExecutionContext workflowContext, ActivityContext activityContext)\n    {\n        return !string.IsNullOrEmpty(ContentType);\n    }\n\n    public override IEnumerable<Outcome> GetPossibleOutcomes(WorkflowExecutionContext workflowContext, ActivityContext activityContext)\n        => Outcome(S[\"Done\"], S[\"Failed\"]);\n\n    public override async Task<ActivityExecutionResult> ExecuteAsync(WorkflowExecutionContext workflowContext, ActivityContext activityContext)\n    {\n        if (InlineEvent.IsStart && InlineEvent.ContentType == ContentType)\n        {\n            if (InlineEvent.Name == nameof(ContentUpdatedEvent))\n            {\n                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.\");\n            }\n\n            if (InlineEvent.Name == nameof(ContentCreatedEvent))\n            {\n                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.\");\n            }\n\n            if (Publish && InlineEvent.Name == nameof(ContentPublishedEvent))\n            {\n                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.\");\n            }\n\n            if (!Publish && InlineEvent.Name == nameof(ContentDraftSavedEvent))\n            {\n                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.\");\n            }\n        }\n","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore.Modules/OrchardCore.Contents/Workflows/Activities/CreateContentTask.cs#L55-L91","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Change the CreateContentTask's ContentType to a different content type than the one that starts the workflow.","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.","Use a different starting event (e.g. ContentCreatedEvent or ContentPublishedEvent) that does not conflict with the task's operation.","Catch InvalidOperationException in custom host code and log/skip the activity run."],"exampleFix":"// before: workflow starts on ContentUpdatedEvent for 'Article', task creates 'Article'\nContentType = \"Article\";\n// after: create a distinct audit content type instead\nContentType = \"ArticleAuditEntry\";","handlingStrategy":"validation","validationCode":"// Before configuring/saving the workflow\nbool loops = triggerEvent == \"ContentUpdatedEvent\"\n    && triggerIsStart\n    && string.Equals(triggerContentType, taskContentType, StringComparison.OrdinalIgnoreCase);\nif (loops) throw new InvalidOperationException(\"CreateContentTask ContentType must differ from the starting event's content type.\");","typeGuard":null,"tryCatchPattern":"try { await workflowManager.TriggerEventAsync(nameof(ContentUpdatedEvent), ...); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"CreateContentTask\") && ex.Message.Contains(\"infinitive loop\"))\n{\n    logger.LogWarning(ex, \"Workflow loop guard triggered; reconfigure the workflow.\");\n}","preventionTips":["Never set a content task's ContentType equal to the content type of the starting content event.","Prefer non-inline workflow execution when creating the same type in response to its own events.","Add a condition activity that checks the created item differs from the triggering item.","Test workflows on a staging tenant where loops surface as this exception instead of hangs."],"tags":["orchardcore","workflows","infinite-loop","contents"],"backgroundTag":"invalid-state-transition","analyzedSha":"4306c0717fe573f6fca1b4955909ddab6a192807","analyzedAt":"2026-09-13T17:41:05.024Z","contentChangedAt":"2026-09-13T17:41:05.024Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}