Skip to content

iOS apps not symbolicating in release mode #4427

Closed

Description

@jamescrosswell

Description

Symbolication / source context for stack traces is missing in release mode on iOS.

This is due to a problem in the .NET SDK when building for Apple platforms in release mode. This issue has been reported to Microsoft and is being tracked in the .NET runtime repository.

If this issue affects your application, please:

  1. Visit the .NET runtime issue
  2. Add a reaction (👍) to indicate this affects you
  3. Consider adding a comment describing your use case

This will help Microsoft prioritise the fix based on community impact.

Workarounds

Until the issue is resolved properly, symbolication on Apple platforms is only possible by disabling stripping. For example, by adding the following to your *.csproj file(s):

<PropertyGroup>
  <EnableAssemblyILStripping>false</EnableAssemblyILStripping>
</PropertyGroup>

Important Note: This may significantly increase the size of your application.

Links

Possible long term fix

In .NET 11 Microsoft are previewing experimental support for CoreCLR on iOS. Since the linking issue that breaks the debug ids (the root cause for this issue) is likely one of the legacy tools used in the linking process in Mono, switching to CoreCLR could very well side step the issue entirely... 🤞🏻 need to test on .NET 11 when a stable preview is available (usually around preview 7).

Further details (original issue report)

It looks like there's a mismatch in the Age field of the DebugID. For example, this is what is being uploaded to Sentry (portable PDB file):

sentry-cli debug-files check ./samples/Sentry.Samples.Maui/obj/Release/net9.0-ios18.0/iossimulator-arm64/Sentry.Samples.Maui.pdb
Debug Info File Check
  Type: portablepdb debug companion
  Contained debug identifiers:
    > Debug ID: 38b96763-ba6a-469d-08f6-03cdcd8e4657-c17c59f
      Arch:     unknown
  Contained debug information:
    > debug, sources
  Usable: yes

But in the event I'm seeing:

"debug_id":"38b96763-ba6a-469d-08f6-03cdcd8e4657-1","debug_file":"/Users/jamescrosswell/code/sentry-dotnet/samples/Sentry.Samples.Maui/obj/Release/net9.0-ios18.0/iossimulator-arm64/Sentry.Samples.Maui.pdb"

If I run sentry-cli debug-files find 38b96763-ba6a-469d-08f6-03cdcd8e4657-1, I see:

38b96763-ba6a-469d-08f6-03cdcd8e4657-1 /Users/jamescrosswell/code/sentry-dotnet/samples/Sentry.Samples.Maui/obj/Release/net9.0-ios18.0/iossimulator-arm64/stripped/Sentry.Samples.Maui.dll [pe]

So the PE header for the stripped assembly that is actually running on the device has an Age field of 1. However this is not a debug file (and can't be uploaded).

Activity

  1. added
    BugSomething isn't working
    .NETPull requests that update .net code
    on Aug 11, 2025
  2. linear commented on Aug 11, 2025

    @linear
  3. removed theissue type on Aug 11, 2025
  4. devperson commented on Aug 11, 2025

    @devperson

    We have the same issue. Can anyone let us know any workaround for this issue?

  5. moved this to Waiting for: Product Owner in GitHub Issues with 👀 3on Aug 11, 2025
  6. jamescrosswell commented on Aug 11, 2025

    @jamescrosswell
    CollaboratorAuthor

    What is suspicious is that we see the full debug id in Debug mode. So in Debug mode we get a debug_id like 3d6b32c9-2dec-4405-93a8-93588829a4f5-c0c54639 in the PE Header, but in Release mode somehow this gets transformed/stripped down to 3d6b32c9-2dec-4405-93a8-93588829a4f5-1 (but the full debug id with the signature/age field is included in the PDB that gets uploaded to Sentry).

    In Sentry, this is where the debug_id gets read from the PE Header when capturing a stack trace:

    // Specification:
    // https://github.com/dotnet/runtime/blob/main/docs/design/specs/PE-COFF.md#codeview-debug-directory-entry-type-2
    //
    // See also:
    // https://learn.microsoft.com/dotnet/csharp/language-reference/compiler-options/code-generation#debugtype
    //
    // Note: Matching PDB ID is stored in the #Pdb stream of the .pdb file.
    if (entry.IsPortableCodeView)
    {
    // Portable PDB Format
    // Version Major=any, Minor=0x504d
    debugId = $"{codeView.Guid}-{entry.Stamp:x8}";
    }

  7. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on Aug 11, 2025
  8. jamescrosswell commented on Aug 12, 2025

    @jamescrosswell
    CollaboratorAuthor

    OK some progress. Actually line 61 above is not executing as expected. For some reason, entry.IsPortableCodeView is returning false and so this code gets executed instead:

    // Full PDB Format (Windows only)
    // Version Major=0, Minor=0
    debugId = $"{codeView.Guid}-{codeView.Age}";

    This should never happen on iOS...

    The check happens here and it's failing because the MinorVersion == 0 (rather than PortablePdbVersions.PortableCodeViewVersionMagic):

    Image

    This may be a bug in the runtime. I'll check with the Microsoft guys.

    Potentially, in the short term, we could work around it by conditionally executing that if block only when running on Windows... and just assume Portable PDB everywhere else?

  9. jamescrosswell commented on Aug 12, 2025

    @jamescrosswell
    CollaboratorAuthor

    @devperson the debug directory entries appear to get modified during linking. As a temporary workaround, you could add an argument like /p:MtouchLink=SdkOnly when building your application. The application would be slightly larger as a result, but would then include enough information for Sentry to be able to correctly identify the PDB symbols associated with each module when symbolicating stack traces (at least for any code in your application... it may not be able to symbolicate code from the .NET SDK).

  10. 50 remaining items

  11. Flash0ver commented on Jan 13, 2026

    @Flash0ver
    Contributor

    Yes, symbolication in Release configuration should work on Android.

  12. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on Jan 13, 2026
  13. jamescrosswell commented on Apr 15, 2026

    @jamescrosswell
    CollaboratorAuthor

    In .NET 11 Microsoft are previewing experimental support for CoreCLR on iOS. Since the linking issue that breaks the debug ids (the root cause for this issue) is likely one of the legacy tools used in the linking process in Mono, switching to CoreCLR could very well side step the issue entirely... 🤞🏻 need to test on .NET 11 when a stable preview is available (usually around preview 7).

  14. added
    BugSomething isn't working
    and removed
    BugSomething isn't working
    on Jul 16, 2026
  15. jamescrosswell commented on Aug 2, 2026

    @jamescrosswell
    CollaboratorAuthor

    More good news, it looks like Microsoft have found the root cause and a fix is on the way:

    Hopefully that makes it into a service release for .NET 10 but I'm guessing we'll see it in .NET 11 at the very latest.

  16. jamescrosswell commented on Aug 5, 2026

    @jamescrosswell
    CollaboratorAuthor

    The fix has been merged. That should make it into the next service release for .NET 10. Just need to bump to the latest (next patch Tuesday) and double check symbolication works again.

    Note

    This is not relevant for .NET 11 at all since this is an issue with the tooling for Mono and the runtime is moving from Mono to CoreCLR on iOS in .NET 11.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

.NETPull requests that update .net codeBugSomething isn't working

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions