OrchardCMS/OrchardCore · error · InvalidOperationException
The cloned content item doesn't contain an AutoroutePart.
Error message
The cloned content item doesn't contain an AutoroutePart.
What it means
AutoroutePartHandler.CloningAsync generates a unique absolute path for the cloned item, but first requires the clone (CloneContentItem) to already carry an AutoroutePart. If the cloned content item lacks that part it throws InvalidOperationException, indicating the clone operation produced an item inconsistent with the source.
Solutions
- Ensure the content type definition includes AutoroutePart on both source and clone before cloning.
- Use the standard IContentManager clone APIs instead of manually constructing the clone item.
- Attach an AutoroutePart to the clone before the Cloning handler runs, copying Path from the source.
- Run a migration to re-add AutoroutePart to legacy items missing it.
Example fix
// before var clone = new ContentItem(); await _contentManager.CloneAsync(contentItem); // after var clone = contentItem.Clone(); clone.Weld(new AutoroutePart()); await _contentManager.CreateAsync(clone);
Defensive patterns
Strategy: validation
Validate before calling
if (!clone.TryGet<AutoroutePart>(out _)) throw new InvalidOperationException("Clone must carry AutoroutePart before cloning."); Type guard
static bool HasAutoroute(ContentItem item) => item.TryGet<AutoroutePart>(out _);
Try / catch
try { await _contentManager.CloneAsync(item); }
catch (InvalidOperationException ex) when (ex.Message.Contains("AutoroutePart"))
{
logger.LogError(ex, "Clone of {Id} lacks AutoroutePart", item.ContentItemId);
throw new ValidationException("Source type must include AutoroutePart for cloning.");
} Prevention
- Keep AutoroutePart in the type definition for routable types
- Use standard clone APIs, never hand-built clones
- Audit imported items for missing parts before cloning
- Write migrations when removing parts from a content type
When it happens
Trigger: Cloning a content item whose type has AutoroutePart attached to the source but where the clone pipeline removed/did not copy the part (e.g. clone created manually without parts, or type definitions changed between source and clone).
Common situations: Custom code calling IContentManager.CloneAsync with a hand-built clone content item; a content type where AutoroutePart was removed after items were created; recipe/import flows constructing clones without copying all parts.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- The cloned content item doesn't contain an AliasPart.
- The cloned content item doesn't contain a LocalizationPart.
- string.Join(", ", result.Errors)
- Content item not found
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/f55c6a7595dcfed1.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore.Modules/OrchardCore.Autoroute/Handlers/AutoroutePartHandler.cs:151
}
public override async Task CreatedAsync(CreateContentContext context, AutoroutePart part)
{
await GenerateContainerPathFromPatternAsync(part);
await GenerateContainedPathsFromPatternAsync(context.ContentItem, part);
}
public override async Task UpdatedAsync(UpdateContentContext context, AutoroutePart part)
{
await GenerateContainerPathFromPatternAsync(part);
await GenerateContainedPathsFromPatternAsync(context.ContentItem, part);
}
public override async Task CloningAsync(CloneContentContext context, AutoroutePart part)
{
if (!context.CloneContentItem.TryGet<AutoroutePart>(out var clonedPart))
{
throw new InvalidOperationException("The cloned content item doesn't contain an AutoroutePart.");
}
clonedPart.Path = await GenerateUniqueAbsolutePathAsync(part.Path, context.CloneContentItem.ContentItemId);
clonedPart.SetHomepage = false;
clonedPart.Apply();
await GenerateContainedPathsFromPatternAsync(context.CloneContentItem, part);
}
public override Task GetContentItemAspectAsync(ContentItemAspectContext context, AutoroutePart part)
{
return context.ForAsync<RouteHandlerAspect>(async aspect =>
{
var contentTypeDefinition = await _contentDefinitionManager.GetTypeDefinitionAsync(part.ContentItem.ContentType);
var contentTypePartDefinition = contentTypeDefinition.Parts.FirstOrDefault(x => string.Equals(x.PartDefinition.Name, "AutoroutePart", StringComparison.Ordinal));
var settings = contentTypePartDefinition.GetSettings<AutoroutePartSettings>();
if (settings.ManageContainedItemRoutes)
{View on GitHub (pinned to 4306c0717f)