Skip to content

BackgroundService.stopRecorder - LateInitializationError crash#4545

Open
aaravgarg wants to merge 2 commits intomainfrom
fix/android-crash-background-service-late-init
Open

BackgroundService.stopRecorder - LateInitializationError crash#4545
aaravgarg wants to merge 2 commits intomainfrom
fix/android-crash-background-service-late-init

Conversation

@aaravgarg
Copy link
Collaborator

Summary

  • Guard stopRecorder() and stop() methods with _status check before accessing _service
  • Prevents LateInitializationError when these methods are called before init() completes
  • Returns early with a debug log instead of crashing

Crash Stats

Test plan

  • Verify recorder start/stop still works after initialization
  • Test calling stopRecorder before init (should log warning, not crash)

🤖 Generated with Claude Code

…rror

Check _status before accessing _service in stopRecorder and stop methods
to prevent LateInitializationError when called before init() completes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@aaravgarg aaravgarg requested a review from mdmohsin7 February 1, 2026 23:26
Copy link
Contributor

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

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 correctly addresses a LateInitializationError crash by adding guards to the stop() and stopRecorder() methods. While this is a good step, the current implementation introduces a subtle but critical race condition. The _status variable is updated before the background service is fully configured, which could lead to other errors if these methods are called during the asynchronous initialization process. My review includes critical comments that detail this issue and propose a more robust solution to ensure the service's stability.

Comment on lines +203 to +206
if (_status == null) {
Logger.debug('BackgroundService.stop: service not initialized');
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

While this guard prevents the LateInitializationError, a race condition still exists. The init() method is async and sets _status to initiated before awaiting the _service.configure() call. This means stop() could be called after _service is instantiated but before it's fully configured. Calling invoke() on an unconfigured service can lead to unpredictable behavior or other errors.

To fix this properly, _status should only be set after _service.configure() has completed. This ensures that any method guarded by _status == null will only proceed when the service is fully initialized and configured.

Here is the recommended change for the init() method:

Future<void> init() async {
  _service = FlutterBackgroundService();
  // The status should not be set here.

  await _service.configure(
    // ... configurations
  );

  // Set status only after configuration is complete.
  // Also, the redundant status assignment at the end of the original method can be removed.
  _status = BackgroundServiceStatus.initiated;
}

Since the init() method is not part of this PR's changes, I'm providing this feedback here. Addressing this is critical for service stability.

Comment on lines +253 to +256
if (_status == null) {
Logger.debug('BackgroundService.stopRecorder: service not initialized');
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

This method has the same critical race condition as the stop() method. The _status == null check is insufficient because _status is set before the service is fully configured in the async init() method. This could lead to _service.invoke() being called on an unconfigured service.

Please see my comment on the stop() method for a detailed explanation and the recommended fix in the init() method to resolve this.

Only set _status = initiated after _service.configure() finishes to
prevent race condition where stop/stopRecorder could be called while
the service is still being configured.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant