Skip to content

fix(grouping): Handle UE 5.8 ensure and ensureMsgf frames in Unreal Engine stack trace rules - #126685

Merged
bitsandfoxes merged 2 commits into
getsentry:masterfrom
tustanivsky:feat/unreal-58-ensure-rules
Nov 3, 2026
Merged

bitsandfoxes merged 2 commits into
getsentry:masterfrom
tustanivsky:feat/unreal-58-ensure-rules

Conversation

@tustanivsky

@tustanivsky tustanivsky commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

This PR extends the default stack trace rules for Unreal Engine to cover ensure events that currently aren't matched by any of the existing rules, so the engine's internal ensure handling and SDK capture frames are not excluded from grouping and culprit selection.

Similar changes were introduced earlier in scope of:

New rules are only added to the current all-platforms@2026-01-20 config, older configs are left unchanged.

Key changes

Unreal Engine has two ensure code paths which changed independently across engine versions. Below is the engine function each ensure variant goes through, verified with events for all four variants on every engine version available in Unreal SDK's CI (Linux 5.2-5.8, Windows 5.5-5.8, macOS 5.8):

Engine version ensure / ensureAlways ensureMsgf / ensureAlwaysMsgf
5.2 - 5.3 DispatchCheckVerify (existing rule) DispatchCheckVerify (existing rule)
5.4 - 5.7 UE::Assert::Private::ExecCheckImplInternal (existing rule) UE::Assert::Private::EnsureFailed (new rule)
5.8 UE::Assert::Private::CheckEnsureFailed (new rule) UE::Assert::Private::EnsureFailed (new rule)

Ensures in UE 5.8 (ensure, ensureAlways)

Starting from UE 5.8 the ensure macro no longer goes through UE::Assert::Private::ExecCheckImplInternal (the function is removed from the engine) and calls UE::Assert::Private::CheckEnsureFailed instead, so the existing rule for UE 5.4 and newer doesn't match these events anymore.

Suggested rule:

family:native stack.function:UE::Assert::Private::CheckEnsureFailed*   v+app -app ^-app

Example events (UE 5.8, macOS):

Ensures with messages in UE 5.4 and newer (ensureMsgf, ensureAlwaysMsgf)

Unlike ensure, the ensureMsgf macro has been calling UE::Assert::Private::EnsureFailed since UE 5.4, so these events were never matched by the existing rules.

Suggested rule:

family:native stack.function:UE::Assert::Private::EnsureFailed*        v+app -app ^-app

Example events (UE 5.8, macOS):

Note that ensureMsgf calls UE::Assert::Private::EnsureFailed from a compiler-generated lambda named after the enclosing function (e.g. MyFunction::lambda::operator()), which becomes the culprit. The enclosing function frame itself is often not present in the stacktrace, so this lambda is intentionally kept in-app.

Impact

Grouping of the following events will change, and existing issues are expected to be regrouped:

  • ensure / ensureAlways events from UE 5.8
  • ensureMsgf / ensureAlwaysMsgf events from UE 5.4 and newer

This applies to all native platforms:

  • macOS and iOS: all frames of the game binary are currently marked as in-app by the package:**.app/Contents/**, package:/Users/** and app bundle container rules, so the culprit for these events points to the SDK's stack unwinding function (e.g. sentry__unwind_stack_libunwind_mac) instead of the code that triggered the ensure. With the new rules, the engine's ensure handling and SDK capture frames are marked as non-app.
  • Windows and Linux: frames are non-app by default, so the culprit for these events currently points to whatever frame happens to be marked as in-app by project rules, or to the SDK's stack unwinding function if there are none. With the new rules, all frames below the matched one become in-app (v+app), the same way as for ensure events from UE 5.4-5.7 today.

Custom rules still take precedence over the defaults. However, projects that rely on frames being non-app by default and only mark their own code as in-app will now also see engine frames (e.g. FEngineLoop::Init, GuardedMain) marked as in-app for these events.

@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label Oct 7, 2026
@tustanivsky tustanivsky changed the title fix(grouping): Handle UE 5.8 ensure and ensureMsgf frames in Unreal Engine stack trace rules fix(grouping): Handle UE 5.8 ensure and ensureMsgf frames in Unreal Engine stack trace rules Oct 7, 2026
@lobsterkatie

Copy link
Copy Markdown
Member

projects that rely on frames being non-app by default and only mark their own code as in-app will now also see engine frames (e.g. FEngineLoop::Init, GuardedMain) marked as in-app for these events.

Can we add rules for those engine frames to mark them as such, and have them therefore marked as out of app? Not sure if any of the existing categories would be accurate or if we'd need a new category and a corresponding category -> non-in-app rule, but either way, seems like we'd want to preserve current in-app behavior here, no?

@tustanivsky

Copy link
Copy Markdown
Contributor Author

The problem is that we can't really distinguish between engine frames and actual game code in Unreal.

Packaged builds link the engine into the same binary as the game so package-based rules won't help here. Function names aren't a reliable signal either since engine code has no dedicated namespace and its classes follow the same naming conventions as game code so they will likely overlap.

Therefore v+app looks like the most sensible default similar to what existing Unreal rules already do. For more precise control customers will still have to apply project-level rules.

@lobsterkatie

Copy link
Copy Markdown
Member

The problem is that we can't really distinguish between engine frames and actual game code in Unreal.

Packaged builds link the engine into the same binary as the game so package-based rules won't help here. Function names aren't a reliable signal either since engine code has no dedicated namespace and its classes follow the same naming conventions as game code so they will likely overlap.

Therefore v+app looks like the most sensible default similar to what existing Unreal rules already do. For more precise control customers will still have to apply project-level rules.

Ah, got it. That makes sense, thanks.

@tustanivsky
tustanivsky marked this pull request as ready for review November 2, 2026 07:22
@tustanivsky
tustanivsky requested a review from a team as a code owner November 2, 2026 07:22
@bitsandfoxes bitsandfoxes added the Trigger: getsentry tests Once code is reviewed: apply label to PR to trigger getsentry tests label Nov 3, 2026
@bitsandfoxes
bitsandfoxes merged commit 99d1435 into getsentry:master Nov 3, 2026
129 of 130 checks passed

This branch was successfully deployed

1 active deployment
Preview — 0c0a831b Deployed Nov 3, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components Trigger: getsentry tests Once code is reviewed: apply label to PR to trigger getsentry tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants