If you ship a game on Unreal, you already know the feeling: the build's out, it's running fine on every machine in the studio, and then the crash reports you can't see start piling up somewhere you can't reach. Unreal is a fantastic engine to build on, but the moment your game leaves your hands, you're flying blind unless you've set up somewhere for those crashes to land. This post is about making that part painless, so the morning after you ship you're looking at a clean list of what to fix instead of refreshing your reviews and bracing.

Here's the good news, and it's genuinely good news: you don't have to build any of this from scratch. Unreal already has a crash reporter. The CrashReportClient dialog that pops up when a game dies is built into the engine, it's well-made, and it already does the hard work of catching the crash and packaging it up. The only catch is that by default it sends everything to Epic. Useful for Epic. Not useful for you, because you can't see a single one of them.

So you don't replace Unreal's crash pipeline. You just point it at yourself. BugSplat's Unreal integration redirects that existing crash flow to your dashboard, symbolicates the reports, groups them by root cause, and hands you the call stacks Epic was quietly collecting and you weren't. Across every platform Unreal ships to: Windows, macOS, Linux, iOS, Android, and the consoles. Set it up once, and your whole team can read crashes from anywhere your game runs, no debugger required.

Two ways in: the plugin or the full integration

Before you start, one decision worth making up front, because it saves you from redoing work later: there are two ways to wire BugSplat into Unreal, and they're built for two different moments.

The plugin is for getting up and running fast. You install it from the Unreal Marketplace or drop it into your project's Plugins folder, fill in a few fields in Project Settings, and you're reporting crashes in minutes, no build pipeline required. It writes the DataRouterUrl for you, can upload symbols automatically as a post-build step, and handles the mobile-specific setup for iOS and Android including hang detection. It's the right call when you're evaluating BugSplat, developing locally, or just want to see your own crashes symbolicated without touching CI. For a solo dev or a small team that builds from the editor, the plugin may be all you ever need.

One thing to know, and it's the line that separates the two paths: the plugin's automatic symbol upload puts your Client ID and Client Secret in DefaultEngine.ini, which is fine on your machine but should never ship in a release build. Those are credentials. You don't want them in a packaged game going out the door.

The full integration is for shipping. When you've got a dedicated build machine or a real CI pipeline, you move symbol upload out of the plugin and into an explicit build step using our symbol-upload CLI, authenticated with an OAuth Client ID/Secret pair that lives in your build environment, not your game. This is the production-grade path, and it unlocks the things a shipping title actually needs:

  • Symbol upload in CI, handling .exe, .dll, .pdb, Linux .psym, and mobile .dSYM files as part of every build, with no credentials baked into your game.
  • Full control over CrashReportClient, including rebuilding it from engine source to replace the default "this is being sent to Epic" text with your own, so players see your studio, not a confusing third party.
  • Custom support responses shown to players right after they submit a crash, including localized messages keyed by BugSplatApplicationKey.
  • Licensee build support, for forks of Unreal (Oculus and others) that block crash uploads by default and need a recompile flag to report at all.
  • Dedicated server reporting on Windows and Linux, so your backend crashes land in the same dashboard as your client crashes.

The honest summary: start with the plugin to prove it works and see your first symbolicated crash. Move to the full integration before you ship, so your release builds are clean, credential-free, and fully under your control. Most teams do exactly that, and the two aren't mutually exclusive, you can use the plugin in the editor and the CLI in CI on the same project.

The rest of this post covers the mechanics that apply to both paths.

Setting up the plugin

You can wire this up by hand, but the BugSplat Unreal plugin exists so you don't have to. Install it, open Edit > Project Settings, scroll to the BugSplat section, and fill in five fields: Database, Application, Version, Client ID, and Client Secret. That's the integration.

The plugin also handles the thing people used to get wrong: the DataRouterUrl in DefaultEngine.ini. That URL is what redirects Unreal's CrashReportClient to BugSplat instead of Epic, and the plugin can write it for you when you enable the option. If you'd rather set it yourself, it looks like this:

[CrashReportClient]
DataRouterUrl="https://{database}.bugsplat.com/post/ue4/{appName}/{appVersion}"

For packaged builds you'll want to make sure Include Crash Reporter and Include Debug Files in Shipping Builds are enabled in project settings, otherwise the reporter or your symbols won't ship and your reports come back empty or unsymbolicated.

Symbols, the automated way

You know the refrain by now: no matching symbols, no readable stack. Unreal makes this easier than most. With the plugin, generate a Client ID and Client Secret on the Integrations page, check Enable Automatic Symbol Uploads, and a symbol-upload step gets added to your build's PostBuildSteps so your reports come back with function names and line numbers automatically. In CI, you run that same symbol-upload step yourself with credentials from your build environment, as covered above. Either way the goal is identical: fresh symbols on every build, so you never ship a release whose crashes you can't read.

Attributes for free

This is a nice one. BugSplat pulls metadata straight out of the CrashContext.runtime-xml file that Unreal attaches to every crash report, and turns those values into searchable attributes in the web app, no code changes required. You can also add your own fields as child properties of RuntimeProperties or GameData in the crash context, things like user ID, level, or session ID, and they show up as columns you can filter and group by. So "crashes on this map" or "crashes in this build for this user" is a filter, not a forensic exercise.

Asserts, checks, and ensures

Unreal's own assertion macros can feed BugSplat too, which is worth setting up because it catches problems before they become full crashes. Checks and verifies report automatically, since they terminate the app. Ensures are the interesting case: they flag a problem without killing the game, and getting them to report takes a little configuration.

The short version: ensures report by default in Development builds. To keep them reporting in Shipping builds, set bUseChecksInShipping = true in your *.Target.cs. At runtime, core.EnsuresAreErrors (default 1) controls whether ensures actually send reports. If ensures start generating too much volume in production, HandleEnsurePercent lets you sample them instead of drowning in them. We've got a full guide on assert/check/ensure configuration if you want to tune this properly.

A couple of field notes

Two things that save real debugging time. Unreal's default HTTP timeout is 30 seconds, and large crash uploads on slow connections can blow past it and fail silently. If you see uploads failing on the Error page, bump the timeouts in DefaultEngine.ini:

[HTTP]
HttpConnectionTimeout=90
HttpActivityTimeout=90
HttpTotalTimeout=90

And for testing, you don't need to wait for a real crash. Run debug crash from the console (or -ExecCmds="debug crash" for a server build) to force one and confirm your whole pipeline works end to end before you ship.

Why this is the right setup for game development

Unreal already does the hard part of catching crashes. The gap was always visibility, the reports were going to Epic and you were flying blind on your own game. Close that gap and you've got symbolicated crashes from every platform, attributed by level and build and user, landing in one dashboard that your whole team can read without a debugger. One person sets it up. Everyone benefits. That's the bar.


Full Unreal setup, including the plugin and the assert/check/ensure guide, is in the docs: docs.bugsplat.com

Want to see your own Unreal crashes symbolicated? Start a free trial and force a test crash in a few minutes.