Detecting and Removing Broken SXA Renderings Using PowerShell
When working with Sitecore SXA, especially in large, content-heavy implementations, broken or orphaned rendering nodes can silently accumulate over time—typically through branch templates, content duplication, or manual edits. While these broken nodes may not immediately cause visible front-end issues, they can create overwhelming log entries and raise concerns.
In this post, I'll demonstrate how we discovered these broken rendering nodes, identified their root causes, and developed a script to efficiently clean them up across a large content tree.
The unlikely part about this is we do get these in the broken links report but it is difficult to separate it out from the whole list of broken links and solve them. These errors are not flooded in the logs but they do peak when a page with these orphaned renderings is loaded
Uncovering Hidden Layout Issues in SXA
While scanning our SXA-powered Sitecore solution logs, we encountered the following errors related to SXA:
ERROR SXA: Could not find 'id' attribute for node <r uid="{B6E891B4-C12F-40C9-9229-10FF182A4531}" ds="{4E3AF08A-C241-461B-B999-CB95839791C6}" />
In addition to the common orphaned rendering issues, we also encountered a few other rendering errors that stem from broken personalization logic. These include:
Missing
s:id
attributes on<r>
nodes that contain<ruleset>
tags, indicating broken personalization rules.Could not find 'id' attribute for node <r uid="{96F075F7-0EE1-4216-B7BD-72397AC2879E}"> <rls> <ruleset> <rule uid="{00000000-0000-0000-0000-000000000000}" name="Default"> <conditions> <condition uid="9794B872B1084A6EA81A2F22DC717196" id="{4888ABBB-F17D-4485-B14B-842413F88732}" /> </conditions> <actions> <action uid="9D8D12E7A3E84823BD1C1429EDF9571B" id="{25F351A1-712D-45F8-857D-8AD95BB2ACE9}" /> </actions> </rule> </ruleset> </rls> </r>
Internal flags such as
cac="1"
andvbd="1"
, which are typically used by Sitecore to track conditional rendering behavior or variant-based display logic in SXA.<r uid="{318F374F-D98B-4FEA-B616-331023880437}" s:cac="1" s:vbd="1" />
While this blog focuses on identifying and fixing the most common type of orphaned rendering—rendering nodes missing s:id
but containing a uid
and possibly a ds
—the base script shared here can be extended to detect and clean up these personalization-related issues as well.
Decoding the Rendering Node Error
This error comes from Sitecore SXA (Sitecore Experience Accelerator) while it’s trying to render a component (or a “rendering”) on a page.
Sitecore renderings (i.e., visual components like banners, grids, etc.) are defined by a unique id in the layout XML. This id tells Sitecore which rendering item to use.
In the XML above, we have a rendering node (
Why Missing s:id Breaks SXA Rendering
Sitecore needs the id to know:
- Which rendering to show
- How to connect this rendering with personalization rules (like show/hide for certain users)
But here, the node only has a uid (which is just a unique reference used in layout xml), and a
Why These Broken Renderings Exist
There are a few common causes:
- Manual XML editing — someone may have altered the layout field directly and removed the s:id
- Content Migration — When content is copied to a new environment, the original page renderings might become unnecessary.
- Programmatic bugs — custom scripts or deployments that inserted or copied renderings incompletely
- Deleted rendering items — the rendering item was deleted from Sitecore, but its reference still lingers in the layout field
- Improper serialization or deserialization — such as when syncing items across environments
The Fix Path: Restore Valid Renderings or Clean Up Orphans
To fix this:
- Either restore the missing rendering id (if you know what it was supposed to be)
- Or remove the entire
node if it can't be recovered — because it’s now an orphan
In our case, the content was migrated to a newer version of Sitecore, and as a result, some rendering definitions (IDs) were lost or became invalid.
The Fix: PowerShell Extension Script
We wrote a script to:
- Scan: Detect all content items with broken rendering nodes, and generate a report showing Orphaned renderings in
__Renderings
with noid
but withuid
ords
- Fix: Clean up the nodes and publishing them while keeping a log of every item updated.
$report = @()
$itemsScanned = 0
$itemsModified = 0
$root = Get-Item -Path "master:/sitecore/content/test-project/www/Home"
$items = Get-ChildItem -Path $root.Paths.Path -Recurse
foreach ($item in $items) {
$itemsScanned++
$hasFieldChanges = $false
$fieldsToCheck = @("__Renderings", "__Final Renderings")
foreach ($fieldName in $fieldsToCheck) {
$field = $item.Fields[$fieldName]
if ($field -and $field.Value -like "*<r*") {
try {
$xml = New-Object System.Xml.XmlDocument
$xml.PreserveWhitespace = $true
$xml.LoadXml("<rList>" + $field.Value + "</rList>")
} catch {
Write-Warning "Invalid layout XML in $fieldName on item: $($item.Paths.Path)"
continue
}
$originalXml = $field.Value
$nodesRemoved = @()
foreach ($rNode in $xml.SelectNodes("//r")) {
$sId = $rNode.GetAttribute("s:id")
$uid = $rNode.GetAttribute("uid")
$ds = $rNode.GetAttribute("s:ds")
# Remove only if uid + ds exist and s:id is missing
if ([string]::IsNullOrEmpty($sId) -and
-not [string]::IsNullOrEmpty($uid) -and
-not [string]::IsNullOrEmpty($ds)) {
$nodesRemoved += $rNode.OuterXml
$rNode.ParentNode.RemoveChild($rNode) | Out-Null
}
}
$afterXml = $xml.InnerXml.Replace("<rList>", "").Replace("</rList>", "")
if ($nodesRemoved.Count -gt 0) {
$item.Editing.BeginEdit()
try {
$field.Value = $afterXml
$item.Editing.EndEdit()
$itemsModified++
$hasFieldChanges = $true
foreach ($removedNode in $nodesRemoved) {
$report += [PSCustomObject]@{
ItemPath = $item.Paths.Path
ItemID = $item.ID.Guid
Field = $fieldName
UID = $uid
DS = $ds
RemovedNode = $removedNode
BeforeXML = $originalXml
AfterXML = $afterXml
}
}
} catch {
$item.Editing.CancelEdit()
Write-Warning "Failed to save changes on: $($item.Paths.Path)"
}
Publish-Item -Item $item `
-Target "web" `
-PublishMode Smart `
-Recurse:$false `
-RepublishAll:$false
}
}
}
if (-not $hasFieldChanges) {
Write-Host "🔍 No matching orphaned renderings in $($item.Paths.Path)"
}
}
# Output Report
if ($report.Count -gt 0) {
$report | Show-ListView -Property ItemPath, Field, UID, DS, RemovedNode, BeforeXML, AfterXML `
-Title "Fixed Orphaned Rendering Nodes (UID + DS, missing s:id)" `
-InfoTitle "Fix Summary" `
-InfoDescription "Removed rendering nodes with uid and ds, but missing s:id"
Write-Host "`nCompleted. Orphaned rendering nodes were removed." -ForegroundColor Green
} else {
Write-Host "No orphaned rendering nodes matching the criteria found!" -ForegroundColor Green
}
Write-Host ""
Write-Host "Items scanned: $itemsScanned"
Write-Host " Items modified: $itemsModified"
Write-Host "Total nodes removed: $($report.Count)"
What Does the Script Do
- Scans all items under root.
- Looks inside
__Renderings
and__Final Renderings
fields. - Finds and removes broken
<r>
nodes that:- Have
uid
ands:ds
- But are missing
s:id
(rendering ID).
- Have
- Saves and publishes the cleaned items.
- Logs what was removed (including path, field, and XML).
- Shows a summary report at the end:
- How many items were scanned
- How many were modified
- Total nodes removed
Wrapping Up the Cleanup
Orphaned rendering nodes in Sitecore SXA might not break your pages, but they clutter the layout, cause hidden errors, and can affect personalization. These issues often go unnoticed—especially after migrations or manual edits.
By automating the detection and cleanup of these broken <r>
nodes using a PowerShell Extension script, we were able to streamline maintenance, reduce log noise, and improve overall rendering stability across our migrated content.
If your solution has gone through major changes or content imports, it's worth running a check like this to avoid future headaches. You can also extend this script further to handle other broken rendering scenarios—like invalid personalization rules or missing variant configurations