If you’ve been managing or using Autodesk products for a few years, you’ve probably cracked open a CER file at some point. Customer Error Reporting is Autodesk’s built-in crash reporting system, and it’s been around for a long time. When Civil 3D, AutoCAD, or Revit goes down hard — an unplanned exit — CER packages up what it knows and sends it off. Hardware info, loaded modules, driver versions, last commands, the document being worked on, the faulting code. The whole picture.
For many years that data lived in an XML file. You could open it in Notepad, search for GPU, and have a pretty good idea of what happened in under five minutes. Not fancy. But it worked. That changed with the 2025 product line.
A Common Misconception
Most people assume CER data is just for Autodesk. You submit it, it disappears into their systems, and hopefully a future update fixes whatever broke. That’s how a lot of users think about it. That’s not the whole story.
The crash files live locally on the machine before they ever get uploaded, and there’s a registry key that controls how many are stored on the system. That means you can read them too. And when you do, you stop guessing. I’ve had some real wins in the last few months tracing crashes back to specific hardware configurations, environment issues, customization conflicts, and bad DWG files causing unplanned exits. CER has become my favorite first stop when something doesn’t add up, when a user is reporting repeated crashes, or when I spot something on my radar in a dashboard.
I liked it enough that I submitted sessions on using CER to solve crashes and lost productivity for Autodesk University 2026. The data is genuinely useful beyond individual troubleshooting — it’s a way to build a picture of how your Autodesk users are doing across the entire company, including current update versions and hardware driver health fleet-wide.
What Changed with CER v7
CER v7 replaced XML with PB files. Protocol Buffers. Binary format. Open one in a text editor now and you get noise. The first time most CAD managers ran into this it wasn’t a great moment.
The reasoning behind the change is solid. XML files were growing, Autodesk was capturing more crash detail, and binary storage is smaller and faster. Integration with Windows Error Reporting also improved, which means better capture rates on crashes the older system sometimes missed. Real infrastructure work. It just broke every workflow users had built around opening that XML file.
Depending on the crash, you may also see a .dmp memory dump alongside the .pb, or multiple .pb files depending on the types of data captured. Two file types, neither of them readable out of the box.
One other change worth knowing: starting with the 2025 products, CER data is sent automatically. Before that, users saw a dialog after a crash and had to choose whether to submit. That dialog is gone now. Reporting happens in the background. For enterprise environments that’s actually good news — your crash data is more complete, and you’re not relying on users to click submit in a moment of frustration.
Where the Files Live
Files land locally before upload at:
C:\Users\Username\AppData\Local\Autodesk\CER
Each crash creates a folder with two levels of subfolders — a machine hash and a timestamp. Inside that folder you will find up to three .pb files:
- rawdata-t1.pb — crash identity, OS version, exception code and module, full product inventory
- rawdata-t2.pb — additional runtime data, varies by crash type
- graphic-data-t1.pb — GPU adapter name, driver version, DirectX info, VRAM
Retention Setting
Default retention is five crash reports per product. If you’re supporting more than a handful of machines that’s not enough. Change that number before you need it. Add a REG_DWORD value named MaxRetainedCount at:
HKEY_CURRENT_USER\Software\Autodesk\SendMiniDmp\Settings
The default value is 5. Set it higher across your fleet via Group Policy or Intune before the next major crash wave.
The Tool That Unlocks the Files
Once you know the .pb file exists and where to find it, the next question is how to actually open it. That’s where cer_rawdataviewer.exe comes in. This is Autodesk’s own viewer tool that ships with the 2025 products. You’re not downloading a third-party utility or finding something on a forum — it’s already on the machine at:
C:\Program Files\Autodesk\Autodesk CER\service\cer_rawdataviewer.exe
The tool takes a .pb file as input and converts it to JSON you can actually read. No admin rights required.
One critical thing to know before you start: the decoder writes its output to stderr, not stdout. A plain redirect will produce an empty file. You must use 2>&1 to capture the output. The output also begins with a timestamp log line that must be stripped before the JSON can be parsed. The PowerShell methods below handle this automatically.
Confirm the tool is present first:
Test-Path "C:\Program Files\Autodesk\Autodesk CER\service\cer_rawdataviewer.exe"
Returns True: ready to go. Returns False: the machine does not have a 2025+ product installed.
Method 1 — Command Prompt
The simplest approach. Good for a quick one-off inspection of a single file. Open Command Prompt (no elevation needed) and run:
"C:\Program Files\Autodesk\Autodesk CER\service\cer_rawdataviewer.exe" "C:\path\to\rawdata-t1.pb" > C:\Temp\output.json 2>&1
Open C:\Temp\output.json in VS Code or any text editor. Delete the first line (the timestamp prefix). The remainder is clean JSON.
Method 2 — PowerShell, Single File to JSON
Handles the stderr capture and timestamp stripping automatically, producing a clean JSON file.
$viewer = "C:\Program Files\Autodesk\Autodesk CER\service\cer_rawdataviewer.exe"
$pbFile = "$env:LOCALAPPDATA\Autodesk\CER\HASH_FOLDER\TIMESTAMP_FOLDER\rawdata-t1.pb"
# Replace HASH_FOLDER and TIMESTAMP_FOLDER with the actual folder names on your machine.
# Not sure what they are? Run this first:
# Get-ChildItem "$env:LOCALAPPDATA\Autodesk\CER" -Recurse -Filter "*.pb" | Select-Object FullName
$outFile = "C:\Temp\rawdata-t1.json"
$lines = & $viewer $pbFile 2>&1
$raw = ($lines | ForEach-Object {
if ($_ -is [System.Management.Automation.ErrorRecord]) {
$_.Exception.Message
} else { $_ }
}) -join "`n"
$jsonStart = $raw.IndexOf('{')
if ($jsonStart -ge 0) {
$raw.Substring($jsonStart) | Out-File $outFile -Encoding utf8 -Force
Write-Host "Saved to $outFile"
} else {
Write-Host "No JSON found. Raw output was:"
Write-Host $raw
}
Method 3 — PowerShell, All .pb Files in a Crash Folder
Decodes every .pb file in a single crash folder into separate JSON files. Use this when you want to inspect both rawdata and graphic-data from the same crash.
$viewer = "C:\Program Files\Autodesk\Autodesk CER\service\cer_rawdataviewer.exe"
$cerRoot = "$env:LOCALAPPDATA\Autodesk\CER"
$outDir = "C:\Temp\CER_Extracted"
New-Item -Path $outDir -ItemType Directory -Force | Out-Null
Get-ChildItem -Path $cerRoot -Filter "*.pb" -Recurse | ForEach-Object {
$lines = & $viewer $_.FullName 2>&1
$raw = ($lines | ForEach-Object {
if ($_ -is [System.Management.Automation.ErrorRecord]) {
$_.Exception.Message
} else { $_ }
}) -join "`n"
$jsonStart = $raw.IndexOf('{')
if ($jsonStart -ge 0) {
$outFile = Join-Path $outDir ($_.BaseName + ".json")
$raw.Substring($jsonStart) | Out-File $outFile -Encoding utf8 -Force
Write-Host "Saved: $outFile"
} else {
Write-Host "No JSON found in output for: $($_.Name)"
}
}
Output files are named to match their source: rawdata-t1.json, rawdata-t2.json, graphic-data-t1.json.
Method 4 — PowerShell, Auto-Find Most Recent Crash
Don’t know the hash or timestamp folder name? This finds the most recently modified crash automatically and decodes all of its .pb files.
$cerRoot = "$env:LOCALAPPDATA\Autodesk\CER"
$viewer = "C:\Program Files\Autodesk\Autodesk CER\service\cer_rawdataviewer.exe"
$outDir = "C:\Temp\CER_Extracted"
New-Item -Path $outDir -ItemType Directory -Force | Out-Null
$crashFolder = Get-ChildItem -Path $cerRoot -Recurse -Filter "*.pb" -File |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1 |
ForEach-Object { $_.DirectoryName }
Write-Host "Decoding crash folder: $crashFolder"
Get-ChildItem -Path $crashFolder -Filter "*.pb" | ForEach-Object {
$lines = & $viewer $_.FullName 2>&1
$raw = ($lines | ForEach-Object {
if ($_ -is [System.Management.Automation.ErrorRecord]) {
$_.Exception.Message
} else { $_ }
}) -join "`n"
$jsonStart = $raw.IndexOf('{')
if ($jsonStart -ge 0) {
$outFile = Join-Path $outDir ($_.BaseName + ".json")
$raw.Substring($jsonStart) | Out-File $outFile -Encoding utf8 -Force
Write-Host "Saved: $outFile"
}
}
Bulk Collection: All .pb Files to JSON
Once you have the syntax confirmed, the real value is processing files in bulk. This script finds every .pb file in the CER folder, runs each one through the viewer, and saves the JSON output to a folder you can review or feed into something else.
$viewerPath = "C:\Program Files\Autodesk\Autodesk CER\service\cer_rawdataviewer.exe"
$cerRoot = "$env:LOCALAPPDATA\Autodesk\CER"
$outputDir = "C:\CEROutput"
if (-not (Test-Path $outputDir)) {
New-Item -ItemType Directory -Path $outputDir | Out-Null
}
$pbFiles = Get-ChildItem -Path $cerRoot -Filter "*.pb" -Recurse
if ($pbFiles.Count -eq 0) { Write-Host "No .pb files found."; exit }
foreach ($file in $pbFiles) {
Write-Host "Processing: $($file.FullName)"
$lines = & $viewerPath $file.FullName 2>&1
$raw = ($lines | ForEach-Object {
if ($_ -is [System.Management.Automation.ErrorRecord]) { $_.Exception.Message } else { $_ }
}) -join "`n"
$j = $raw.IndexOf('{')
if ($j -ge 0) {
$outputFile = Join-Path $outputDir ($file.BaseName + ".json")
$raw.Substring($j) | Out-File $outputFile -Encoding utf8 -Force
Write-Host " Saved: $outputFile"
} else {
Write-Host " WARNING: No JSON output for $($file.Name)"
}
}
Write-Host "Done. JSON files saved to $outputDir"
Compiling Crashes into a CSV
JSON isn’t your only option. You can compile the key fields from every rawdata-t1.pb across all crash folders into a single CSV — which opens a fast path into Power BI or Excel.
# ------------------------------------------------------------
# Autodesk CER Export - Blog Example
# Supports pre-2025 XML (dmpuserinfo.xml) and 2025+ PB files
# Outputs a CSV ready for Power BI or AI analysis
# ------------------------------------------------------------
$CerRoot = "X:\Misc\AutodeskCER"
# Replace X:\Misc\AutodeskCER with the root folder where you
# collect CER folders from your machines. Each subfolder should
# be a username, containing crash subfolders with .xml or .pb files.
$Output = "C:\Temp\CER_Export.csv"
$CerViewer = "C:\Program Files\Autodesk\Autodesk CER\service\cer_rawdataviewer.exe"
function Get-PbParam {
param ($Params, [string]$Key)
if ($null -eq $Params) { return "" }
$entry = $Params.$Key
if ($null -eq $entry) { return "" }
$vals = $entry.value
if ($null -eq $vals -or $vals.Count -eq 0) { return "" }
return ($vals -join "; ")
}
function Get-PbParams {
param ([string]$CrashFolder, [string]$ViewerExe)
$merged = @{}
if (-not (Test-Path $ViewerExe)) { return $merged }
Get-ChildItem -Path $CrashFolder -Filter "*.pb" -ErrorAction SilentlyContinue | ForEach-Object {
try {
$lines = & $ViewerExe $_.FullName 2>&1
$raw = ($lines | ForEach-Object {
if ($_ -is [System.Management.Automation.ErrorRecord]) {
$_.Exception.Message
} else { $_ }
}) -join "`n"
$jsonStart = $raw.IndexOf('{')
if ($jsonStart -lt 0) { return }
$parsed = $raw.Substring($jsonStart) | ConvertFrom-Json -ErrorAction SilentlyContinue
if (-not $parsed -or -not $parsed.params) { return }
$parsed.params.PSObject.Properties | ForEach-Object {
$merged[$_.Name] = $_.Value
}
} catch {
Write-Verbose "Error decoding $($_.Name): $_"
}
}
return $merged
}
function Get-XmlAttr {
param ($Node, [string]$Attr)
if ($Node -and $Node.Attributes[$Attr]) {
return $Node.Attributes[$Attr].Value
}
return ""
}
function Get-OpenFiles {
param ($UserInfoNode)
$files = @()
if ($UserInfoNode) {
foreach ($child in $UserInfoNode.ChildNodes) {
if ($child.Name -match '\.(dwg|dwt|dxf)$') {
$name = Get-XmlAttr $child "name"
if ($name) { $files += $name }
}
}
}
return ($files -join "; ")
}
$Results = Get-ChildItem -Path $CerRoot -Recurse -Directory | ForEach-Object {
$CrashFolder = $_.FullName
$XmlFile = Join-Path $CrashFolder "dmpuserinfo.xml"
$PbFiles = Get-ChildItem -Path $CrashFolder -Filter "*.pb" -ErrorAction SilentlyContinue
$hasXml = Test-Path $XmlFile
$hasPb = ($PbFiles -and $PbFiles.Count -gt 0)
if (-not $hasXml -and -not $hasPb) { return }
$relative = $CrashFolder.Substring($CerRoot.Length + 1)
$username = $relative.Split('\')[0]
$refFile = if ($hasXml) { $XmlFile } else {
($PbFiles | Sort-Object LastWriteTime | Select-Object -First 1).FullName
}
$crashDateTime = (Get-Item $refFile).LastWriteTime
$row = [ordered]@{
Username = $username
CrashDateTime = $crashDateTime
FormatVersion = if ($hasXml) { "XML" } else { "PB" }
ComputerName = ""
ProductName = ""
ProductVersion = ""
OSVersion = ""
GPUModel = ""
GPUDriver = ""
FaultingModule = ""
ExceptionCode = ""
OpenDWGFiles = ""
}
if ($hasXml) {
try {
[xml]$xml = Get-Content $XmlFile -ErrorAction Stop
$userInfo = $xml.SelectSingleNode("//UserInfo")
if ($userInfo) {
$row.ComputerName = Get-XmlAttr $userInfo "ComputerName"
$row.OpenDWGFiles = Get-OpenFiles $userInfo
}
$productInfo = $xml.SelectSingleNode("//ProductInformation")
if ($productInfo) {
$row.ProductName = Get-XmlAttr $productInfo "name"
$row.ProductVersion = Get-XmlAttr $productInfo "build_version"
}
$osInfo = $xml.SelectSingleNode("//OSInfo")
if ($osInfo) {
$major = Get-XmlAttr $osInfo "MajorVersion"
$minor = Get-XmlAttr $osInfo "MinorVersion"
$build = Get-XmlAttr $osInfo "BuildNumber"
$row.OSVersion = "$major.$minor (Build $build)"
}
$gpu = $xml.SelectSingleNode("//DxDiagInfo/GraphicsDeviceInfo")
if ($gpu) {
$chipType = $gpu.SelectSingleNode("ChipType")
$driverVer = $gpu.SelectSingleNode("DriverFileVersion")
if ($chipType) { $row.GPUModel = $chipType.InnerText.Trim() }
if ($driverVer) { $row.GPUDriver = $driverVer.InnerText.Trim() }
}
$exception = $xml.SelectSingleNode("//RuntimeInformation/Exception")
if ($exception) {
$row.ExceptionCode = Get-XmlAttr $exception "type"
$row.FaultingModule = Get-XmlAttr $exception "module"
}
} catch {
Write-Warning "XML parse error in $XmlFile : $_"
}
}
if ($hasPb) {
$params = Get-PbParams -CrashFolder $CrashFolder -ViewerExe $CerViewer
if ($params.Count -gt 0) {
$row.ProductName = Get-PbParam $params "SP/UPI_PRODUCT"
$row.ProductVersion = Get-PbParam $params "SP/UPI_RELEASE"
$major = Get-PbParam $params "AI/os/MajorVersion"
$minor = Get-PbParam $params "AI/os/MinorVersion"
$build = Get-PbParam $params "AI/os/BuildNumber"
$row.OSVersion = "$major.$minor (Build $build)"
$row.GPUModel = Get-PbParam $params "AI/d3d/AdapterDescription"
$row.GPUDriver = Get-PbParam $params "AI/d3d/DriverVersion"
$row.FaultingModule = Get-PbParam $params "AP/exception/module_name"
$row.ExceptionCode = Get-PbParam $params "AP/exception/code"
}
$userinfoFile = Get-ChildItem -Path $CrashFolder -Filter "*.userinfo" -ErrorAction SilentlyContinue | Select-Object -First 1
if ($userinfoFile) {
try {
$ui = Get-Content $userinfoFile.FullName -Raw | ConvertFrom-Json
if ($ui.computer_name) { $row.ComputerName = $ui.computer_name }
} catch {}
}
}
[pscustomobject]$row
}
$Results | Sort-Object CrashDateTime | Export-Csv $Output -NoTypeInformation -Force
Write-Host ""
Write-Host "Export complete: $Output"
Write-Host "Total records : $($Results.Count)"
$xmlCount = ($Results | Where-Object { $_.FormatVersion -eq "XML" }).Count
$pbCount = ($Results | Where-Object { $_.FormatVersion -eq "PB" }).Count
Write-Host " XML (pre-2025) : $xmlCount"
Write-Host " PB (2025+) : $pbCount"
Taking It Further: Power BI and AI Analysis
Pull that CSV into Power BI and you’ve got a live dashboard showing crash rates by product version, GPU driver distribution, and faulting module frequency across your entire user base. Connect it to a shared folder that updates regularly and the dashboard stays current without manual work.
The other path worth knowing about is feeding the JSON or CSV directly into an AI tool for analysis. Claude and ChatGPT are both solid at this. What feels like a haystack with no needle often has a clear signal buried in it — a driver version showing up disproportionately before faults, a specific module that keeps appearing across machines in the same office, a pattern that only surfaces after a recent update rollout. Drop your CSV into a conversation, describe what you’re managing, and ask it to look for clusters and outliers. You’ll often walk away with a lead you wouldn’t have found manually.
Once you’re pulling CER data consistently, the picture starts coming together fast:
- Hardware dashboard — GPU models, driver versions, and memory configs across your fleet.
- Software version tracking — who’s on what update, and whether crash rates shift after a rollout.
- Crash rate trends — are things getting better or worse after a change you made?
- Cluster analysis — the same faulting module across multiple machines, the same drawing triggering failures on different workstations, a plugin appearing right before a fault.
Single crashes are noise. Clusters are signal. When the same pattern shows up across users, departments, or machines, you’re not troubleshooting anymore — you’re diagnosing. And you can show your work. That changes the conversation with vendors, with IT, and with leadership.
I’ve traced crashes back to specific customization conflicts, data issues, and environment problems that never would have surfaced through a support ticket or call alone. CER data got me there faster almost every time.
The PB to JSON conversion adds a step to a workflow that used to be simpler. But the data quality is better, the capture rate is better, and once you have the process down it’s not much friction. Build a consistent review habit and start treating this data like the diagnostic tool it actually is.
Key Fields Reference
Once decoded, every .pb file exposes its data under a params object. Each key maps to a value array. Here are the most useful fields:
rawdata-t1.pb:
AI/CrashDate -- Date the crash occurred
AI/CrashUUID -- Unique identifier for this crash
AI/os/BuildNumber -- Windows build number
AI/os/MajorVersion -- Windows major version
AP/exception/code -- Exception code (e.g. 0xC0000005)
AP/exception/text -- Exception type (e.g. ACCESS_VIOLATION)
AP/exception/module_name -- DLL or module where the crash occurred
CD/SubscriptionMacID -- Autodesk subscription machine ID
SP/UPI_PRODUCT -- Product code (e.g. CIV3D, ACD)
SP/UPI_RELEASE -- Release year (e.g. 2025)
SP/UPI_FULL_XML -- Full installed product inventory as XML
graphic-data-t1.pb:
AI/d3d/AdapterDescription -- GPU model name
AI/d3d/DriverVersion -- GPU driver version
AI/d3d/DriverDate -- GPU driver date
AI/d3d/DedicatedVideoMemory -- GPU VRAM in bytes
GPU fields only appear when a graphic-data-t1.pb file is present in the crash folder. Not every crash generates one.
-Shaan