Skip to content

Fix: Preserve caller stack trace and timestamp for queued Crashlytics API calls - #16126

Merged
mghaznav merged 6 commits into
mainfrom
ali/cls-record-error-bug-fix
Apr 28, 2026
Merged

mghaznav merged 6 commits into
mainfrom
ali/cls-record-error-bug-fix

Conversation

@mghaznav

@mghaznav mghaznav commented Apr 28, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #16106

Description

This PR fixes a regression introduced in 12.11.0 where custom logged errors (via recordError:) captured the incorrect execution frame and timestamp, resulting in inaccurate stack traces in the Firebase Console.

Background & Context:
When Crashlytics migrated to asynchronous initialization, API calls made immediately after FirebaseApp.configure() were being dropped because the SDK had not finished initializing. To resolve this, [PR #15879](#15879) introduced a promise-based queue (waitForContextInit:) to hold execution of API calls until Crashlytics was ready.

The Bug (Side Effect):
While PR #15879 successfully stopped API calls from dropping, it shifted the execution context of the underlying C-level logging functions. Because methods like FIRCLSUserLoggingRecordError were now being invoked inside the promise callback, the stack trace and timestamp were being captured at the time of the promise resolution, rather than the moment the user actually called the API.

The Fix:
We now snapshot the stack trace synchronously using [NSThread callStackReturnAddresses] and grab the timestamp via time(NULL) directly on the caller's thread. This is how it used to be before the asynchronous change.

Stack Trace

Before this PR

image

Calling frame is missing from the stack.

After

image

Calling frame is present in the stack.

Note: With this update there is one change in the recorded stack as compared to the stacks recorded in 12.10.0 and before. The stack has one less frame since the nesting of the call to record the stack frame has reduced by 1. This has no effect on how the events are grouped.

Testing

  • All existing unit tests pass.
  • Updated unit tests to verify the explicit passing of the mocked stack trace arrays.
  • Audited and tested other Crashlytics API methods (such as recordExceptionModel: and custom logging) to ensure no similar async side effects exist.
  • Ran ./scripts/check.sh locally to verify formatting and linting.

@gemini-code-assist

Copy link
Copy Markdown
Contributor
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

@mghaznav
mghaznav requested review from tejasd and removed request for tejasd April 28, 2026 14:45
@mghaznav

Copy link
Copy Markdown
Contributor Author

/gemini review

@mghaznav mghaznav self-assigned this Apr 28, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request ensures the correct calling frame is included in stack traces for record(error:) by capturing the call stack and timestamp before entering the asynchronous queue. The FIRCLSUserLoggingRecordError signature was updated to accept these values, and unit tests were modified accordingly. A recommendation was made to include a nil check for the error object to avoid the overhead of capturing the call stack when it is not needed.

Comment thread Crashlytics/Crashlytics/FIRCrashlytics.m
@mghaznav
mghaznav requested review from mrober and tejasd April 28, 2026 15:00
Comment thread Crashlytics/Crashlytics/FIRCrashlytics.m
Comment thread Crashlytics/Crashlytics/FIRCrashlytics.m
Comment thread Crashlytics/UnitTests/FIRCLSLoggingTests.m
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Crashlytics no longer reporting non-fatal call line

3 participants