As of Sitecore CLI version 6.0.23, neither the itemres command nor the serialization package subcommand return a non-zero status code when YAML parsing errors occur. This is an issue for build pipelines. YAML parsing errors that occur during item package and resource package generation will result in malformed packages, but the errors will not cause the build pipeline to fail.

For example, if you are building a resource package (IAR) in your build pipeline and one of the YAML files being packaged is malformed, the itemres create subcommand will output an error message similar to this:

[master] Source: serialized items (1 subtrees)
[master] Destination: item package 'items.master.iar.dat'
[master] Loading data...
[master] Error parsing YAML C:\code\Site\serialization\content-block.yml
[master] MANUAL FIX: delete + pull fresh copy, or hand editing
[master] Please fix your yml files to proceed with the serialization!
________________________________________________Resource Packages Report________________________________________________
Created resource package items.master.iar.dat of MASTER database in C:\code\Site\serialization directory

Error messages are output, but the itemres command generates a resource package anyway; an empty, 0 KB resource package. The itemres command will return a 0 exit code (success) and the build will succeed as if there was no problem. Deploy this 0 KB resource package to Sitecore and portions of your content tree could disappear if root items in the IAR file have not been written to the Sitecore databases.

With the package command, an item package will be created, but some or all of your items just won't be deployed to Sitecore when the item package is installed. Not as dramatic as the equivalent issue with resource files where portions of the content tree may disappear, but annoying nonetheless.

I have reported this issue to Sitecore. Hopefully Sitecore will update the package and itemres commands to:

  1. Return a non-zero status code on YAML errors; and
  2. Not create an item package or resource package when errors occur.

Some other errors already cause this behavior. For example, if there is an identical path in two different serialized files that are being packaged, the Sitecore CLI will throw an error, return a non-zero status code, and it won't generate a resource package (though it will still create partial item packages).

In the meantime, there are two things you can do to catch YAML errors in your build pipeline.

The Validate Subcommand

The Sitecore CLI serialization command has a validate subcommand that will catch issues with your YAML files as well as item errors: invalid physical paths, orphaned parent IDs, duplicate item IDs, non-unique paths, and more. The validate subcommand does return a non-zero exit code when it detects these errors.

Add a step to your build pipeline that runs the validate subcommand before the package generation step. It's as simple as running dotnet sitecore ser validate in the same directory that you run your package command. The build pipeline will now fail on most errors. I say most because I've run into a malformed YAML file that wasn't caught by the validate subcommand, but it was reported by the itemres command. That's where the next solution comes in to play.

⚠️WARNING⚠️: if you're building a resource package from Unicorn files using the itemres unicorn subcommand, you can't use the validate subcommand without Sitecore Content Serialization (SCS) configs. If you've got SCS configs, why are you using Unicorn to serialize your items?

Catch YAML Errors in a Script

The following wrapper script for the itemres and package commands will catch YAML parsing errors and return a non-zero status code to fail build pipelines. This script uses the itemres create subcommand as an example, but it will work just as well for the itemres unicorn and the ser pkg create subcommands.

$packageName = "iar"
$iarStagingFolder = "C:\code\Site\output"
$minimumFileSizeInKb = 5

dotnet sitecore itemres create -o "$iarStagingFolder\$packageName" --overwrite --verbose `
  | Tee-Object -Variable itemresOutput

if ($LASTEXITCODE -ne 0) {
  Write-Error "Packaging command failed with exit code $LASTEXITCODE. Review logs above."
  exit $LASTEXITCODE
}

$itemresErrors = @()
$itemresErrorPatterns = @(
  "Error while getting item yml",
  "Error parsing YAML",
  "MANUAL FIX: delete \+ pull fresh copy, or hand editing",
  "Please fix your yml files to proceed with the serialization!"
)
foreach ($pattern in $itemresErrorPatterns) {
  $itemresErrors += $itemresOutput | Select-String -Pattern $pattern
}

if ($itemresErrors) {
  $itemresErrors | ForEach-Object { Write-Error $_ }
  Write-Error "Packaging encountered error(s). Review logs above."
  exit 1
}

$suspiciousIarFiles = Get-ChildItem -Path "$iarStagingFolder" `
  | Where-Object { $_.Extension -in @('.dat', '.itempackage') } `
  | Where-Object { $_.Length -lt ($minimumFileSizeInKb * 1024) }

if ($suspiciousIarFiles) {
  $suspiciousIarFiles | ForEach-Object { Write-Error "$($_.FullName) is smaller than $minimumFileSizeInKb KB." }
  Write-Error "One or more packages are too small, indicating a potential problem. Review logs above."
  exit 1
}

The itemres and package commands usually write "MANUAL FIX: delete pull fresh copy, or hand editing" and "Please fix your yml files to proceed with the serialization!" when a YAML parsing error occurs, so this script watches for those messages in the output. The script also looks for any instances of "Error while getting item yml" and "Error parsing YAML". If any of these messages are found, the script returns an exit code of 1, which will cause build pipelines to fail.

As an additional failsafe, the script will return an exit code of 1 if the output item package or resource package is smaller than 5 KB. You may want to increase this number (the $minimumFileSizeInKb variable) according to your normal package size. For example, if your resource package is normally 1000 KB, perhaps fail the build if the generated resource package is less than 900 KB. A 10% or larger decrease in package size may indicate a YAML error, or the unintentional deletion of a substantial amount of serialized items. Better to catch that in the build than after a deploy to one or all of your environments.

I mentioned at the beginning of this post that this issue affects Sitecore CLI 6.0.23. This is an issue in earlier versions of the Sitecore CLI as well, though I have not checked how far the issue goes back.

If this script helps you, or you've encountered errors that I haven't caught here, let me know in the comments.

Blog feature image by 乐融 高 on Unsplash.