Skip to content

feat(splash): fix reactive error handling to only block bootstrap when necessary#21

Merged
pckimlong merged 1 commit into
mainfrom
dev
Mar 3, 2026
Merged

feat(splash): fix reactive error handling to only block bootstrap when necessary#21
pckimlong merged 1 commit into
mainfrom
dev

Conversation

@pckimlong
Copy link
Copy Markdown
Owner

Reactive task errors now only take over the splash screen when they actually block bootstrap:

  • initial reactive run failure (no previous value), or
  • trigger-caused reactive refresh failure.

Non-trigger runtime reactive failures after successful bootstrap no longer replace app content with splash error UI. Add shouldDisplayReactiveTaskError helper function and tests for reactive error visibility rules.

…n necessary

Reactive task errors now only take over the splash screen when they actually block bootstrap:
- initial reactive run failure (no previous value), or
- trigger-caused reactive refresh failure.

Non-trigger runtime reactive failures after successful bootstrap no longer replace app content with splash error UI. Add shouldDisplayReactiveTaskError helper function and tests for reactive error visibility rules.
@pckimlong pckimlong merged commit 592070e into main Mar 3, 2026
1 check failed
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the user experience during application startup and runtime by making reactive error handling more intelligent. It ensures that the splash screen only displays errors when they are critical to the bootstrap process, avoiding disruptive error overlays for less severe, non-blocking reactive failures that occur after the app has successfully loaded. This change leads to a smoother and less intrusive error reporting mechanism for reactive tasks.

Highlights

  • Refined Reactive Error Handling: Reactive task errors will now only display on the splash screen if they genuinely block the application's bootstrap process. This includes initial reactive run failures (when no previous value exists) or failures during a trigger-caused reactive refresh.
  • Improved User Experience Post-Bootstrap: After successful bootstrap, if a reactive task fails due to a non-trigger runtime refresh, the application content will remain visible instead of being replaced by the splash error UI, preventing unnecessary interruptions.
  • New Error Visibility Helper: A new helper function, shouldDisplayReactiveTaskError, has been introduced to encapsulate the logic for determining when a reactive error should be displayed on the splash screen.
  • Enhanced Test Coverage: New tests have been added to validate the reactive error visibility rules, ensuring the correct behavior of the updated error handling logic.
  • Dependency Updates: Several package dependencies in example/pubspec.lock have been updated to their latest versions.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • CHANGELOG.md
    • Fixed SplashBuilder so reactive errors only take over when they block bootstrap: initial reactive run failure (no previous value), or trigger-caused reactive refresh failure.
    • Non-trigger runtime reactive failures after successful bootstrap no longer replace app content with splash error UI.
    • Added tests for reactive error visibility rules.
  • README.md
    • Updated key behavior documentation to clarify that if a non-trigger runtime refresh fails after a successful reactive run, Riverboot keeps rendering app content instead of showing the splash error screen.
Activity
  • No specific activity (comments, reviews, or progress updates) has been provided for this pull request.
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
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@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 effectively refines the error handling for reactive tasks, ensuring the splash screen only blocks the UI for critical bootstrap failures. The logic is well-encapsulated in the new shouldDisplayReactiveTaskError helper function, and the implementation in SplashBuilder is clean. My main feedback is to enhance the test coverage for the new logic to ensure all scenarios, particularly trigger-caused failures, are explicitly verified.

Comment on lines +284 to 320
test(
'runtime reactive error is hidden when previous value exists',
() {
final runtimeError =
const AsyncError<void>(
'runtime error',
StackTrace.empty,
)
// ignore: invalid_use_of_internal_member
.copyWithPrevious(const AsyncData<void>(null));

final shouldShow = shouldDisplayReactiveTaskError(
reactiveTaskRun: runtimeError,
triggerCausedRefresh: false,
);

expect(runtimeError.hasError, isTrue);
expect(runtimeError.hasValue, isTrue);
expect(shouldShow, isFalse);
},
);

test('initial reactive error is shown when no previous value exists', () {
const initialError = AsyncError<void>(
'initial error',
StackTrace.empty,
);

// Initial load - splash shown, then content
await tester.pumpAndSettle();
expect(find.text('Content'), findsOneWidget);
expect(runCount, 1);
final initialSplashCount = splashBuildCount;

// Now trigger an error WITHOUT changing the trigger
// This simulates a dependency of run() causing a re-run that errors
final container = ProviderScope.containerOf(
tester.element(find.text('Content')),
final shouldShow = shouldDisplayReactiveTaskError(
reactiveTaskRun: initialError,
triggerCausedRefresh: false,
);

// Set error flag and invalidate run provider to simulate re-run
shouldError = true;
container.invalidate(reactiveTaskRunProvider);

// Pump to process the error
await tester.pump();
await tester.pump();
await tester.pump();

// Error screen should be shown
expect(errorScreenShown, isTrue);
expect(find.text('Error - Retry'), findsOneWidget);

// CRITICAL: Splash should NOT have been shown again
// (splashBuildCount should not have increased)
expect(
splashBuildCount,
initialSplashCount,
reason: 'Splash should not show when error occurs without trigger change',
);
expect(initialError.hasError, isTrue);
expect(initialError.hasValue, isFalse);
expect(shouldShow, isTrue);
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

These new unit tests for shouldDisplayReactiveTaskError are great for verifying the new error visibility rules. However, they only cover cases where triggerCausedRefresh is false.

To ensure complete test coverage for the new logic, consider adding a test case for when a trigger-caused refresh fails. This would verify that the error screen is correctly displayed even if there's a previous value, which is a key part of the new behavior.

Here's a suggestion for the new test:

test('trigger-caused reactive error is shown even with a previous value', () {
  final triggerError = const AsyncError<void>(
    'trigger error',
    StackTrace.empty,
  )
  // ignore: invalid_use_of_internal_member
  .copyWithPrevious(const AsyncData<void>(null));

  final shouldShow = shouldDisplayReactiveTaskError(
    reactiveTaskRun: triggerError,
    triggerCausedRefresh: true,
  );

  expect(triggerError.hasError, isTrue);
  expect(triggerError.hasValue, isTrue);
  expect(shouldShow, isTrue);
});

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