ark_error_manager_flutter 1.0.0 copy "ark_error_manager_flutter: ^1.0.0" to clipboard
ark_error_manager_flutter: ^1.0.0 copied to clipboard

Flutter capture hooks and presentation integration for Ark Error Manager.

Ark Error Manager Flutter #

Flutter runtime hooks, build-mode detection, context collection, and presentation integration for ark_error_manager.

The package connects one application-owned ErrorManager to FlutterError.onError and PlatformDispatcher.onError. It does not place the manager in widgets, Presenters, UseCases, repositories, providers, or DI scopes.

Русская версия

Version 1.0 establishes the stable public API described in this guide.

What the adapter captures #

Flutter has two root error paths:

  • FlutterError.onError receives failures caught by Flutter framework callbacks, including build, layout, paint, and explicit FlutterError.reportError calls;
  • PlatformDispatcher.onError receives unhandled root-isolate errors outside Flutter callbacks when no nearer error Zone handles them.

FlutterErrorManagerBinding attaches both paths to the same manager. A root Zone remains application-owned and uses the core ErrorManager.onUncaughtZoneError callback.

Installation #

dependencies:
  ark_error_manager_flutter: ^1.0.0
import 'package:ark_error_manager_flutter/ark_error_manager_flutter.dart';

The Flutter package exports the public core API, so a separate core import is not required in the same file.

Bootstrap composition #

Initialize Flutter, create the manager, attach Flutter hooks, and call runApp inside the same application-owned Zone:

The excerpt focuses on ownership. Application and ApplicationErrorPresentationDelegate are application-defined types; the runnable example contains a complete implementation.

import 'dart:async';

import 'package:ark_error_manager_flutter/ark_error_manager_flutter.dart';
import 'package:flutter/material.dart';

void main() => ApplicationBootstrap().run();

final class ApplicationBootstrap {
  ErrorManager? _manager;
  FlutterErrorManagerBinding? _binding;

  void run() {
    runZonedGuarded(
      _start,
      _onZoneError,
    );
  }

  void _start() {
    WidgetsFlutterBinding.ensureInitialized();

    final GlobalKey<NavigatorState> navigatorKey =
        GlobalKey<NavigatorState>();
    final ErrorManager manager = ErrorManager(
      configuration: ErrorManagerConfiguration(
        environment: FlutterErrorBuildMode.environment(
          deployment: ErrorDeploymentEnvironment.production,
          application: const ErrorApplicationInfo(
            name: 'Example application',
            version: '1.4.0',
          ),
        ),
        classifiers: const <ErrorClassifier>[
          FlutterFrameworkErrorClassifier(),
        ],
        contextProviders: <ErrorContextProvider>[
          FlutterRuntimeErrorContextProvider(),
        ],
        reporters: const <ErrorReporter>[
          DeveloperLogErrorReporter(),
        ],
        presenter: NavigatorErrorPresenter(
          navigatorKey: navigatorKey,
          delegate: const ApplicationErrorPresentationDelegate(),
        ),
      ),
    );
    final FlutterErrorManagerBinding binding =
        FlutterErrorManagerBinding(manager: manager)..attach();

    _manager = manager;
    _binding = binding;
    runApp(Application(navigatorKey: navigatorKey));
  }

  void _onZoneError(Object error, StackTrace stackTrace) {
    final ErrorManager? manager = _manager;
    if (manager == null) {
      Zone.root.handleUncaughtError(error, stackTrace);
      return;
    }
    manager.onUncaughtZoneError(error, stackTrace);
  }
}

The bootstrap object retains the binding only so a controlled application host can later call detach, then flush and close on the manager. Widgets and features do not receive either object.

Hook ownership #

Flutter's handlers are global inside the root isolate. The binding therefore has explicit ownership rules:

  • repeated attach on the same binding is idempotent;
  • attaching a different binding while one is active throws StateError;
  • detach restores handlers that existed before attach;
  • a handler installed by a later external owner is never overwritten during detach;
  • isAttached exposes current ownership state.

This prevents silent hook replacement and stale-manager restoration.

Previous handlers #

FlutterPreviousErrorHandlerPolicy.preserve is the default. The binding sends the error to the manager and then invokes the previous handler. This preserves Flutter's normal debug output and allows intentional composition with an existing host handler.

Use replace when the manager must be the sole owner and the application has already moved the previous handler's behavior into reporters or policy.

Do not install two crash-reporting systems independently and preserve both without checking for duplicate remote reports.

Flutter error details #

Framework errors include FlutterErrorCaptureDetails, which retains the original FlutterErrorDetails for application-local classification, presentation, and recovery. Raw details never appear in ErrorReport.

FlutterRuntimeErrorContextProvider adds bounded diagnostics:

  • target platform and web flag;
  • application lifecycle state;
  • locale list;
  • platform brightness;
  • Flutter library and operation context;
  • Flutter's silent diagnostics flag.

The provider does not collect widget trees, user-entered values, route arguments, or arbitrary framework diagnostics.

Build mode and deployment environment #

FlutterErrorBuildMode.detect() maps Flutter's compile-time constants to core ErrorBuildMode.debug, profile, or release.

FlutterErrorBuildMode.environment(...) combines that value with an explicit deployment target and application identity:

final ErrorRuntimeEnvironment environment =
    FlutterErrorBuildMode.environment(
      deployment: ErrorDeploymentEnvironment.staging,
      application: const ErrorApplicationInfo(
        name: 'Example application',
        version: '1.4.0',
        buildNumber: '87',
        packageIdentifier: 'dev.example.application',
      ),
    );

The adapter does not infer whether a build talks to development, staging, or production services.

Presentation #

NavigatorErrorPresenter adapts the core ErrorPresenter contract to Flutter. It looks up the current context from an application-owned GlobalKey<NavigatorState> and delegates rendering to FlutterErrorPresentationDelegate.

The package does not impose Material dialogs, SnackBars, navigation, or copy. The delegate receives:

  • current root navigation context, which can be null during startup or shutdown;
  • raw application-local ErrorIncident;
  • passive or blocking presentation directive.

The delegate must handle a null context without throwing.

Relationship to other Ark packages #

No Ark package depends on Ark Error Manager. Existing propagation remains the integration:

  • ark_mvp_flutter reports unhandled runtime failures through FlutterError.reportError;
  • ark_di_flutter forwards unhandled scope-close failures to the owning Zone;
  • usecase_forge_flutter reports widget-side failures through Flutter;
  • Ark Data Layer does not swallow unexpected operation failures.

One root binding receives those errors without manager injection into feature objects.

Controlled shutdown #

For hosts that support controlled shutdown:

binding.detach();
await manager.flush();
await manager.close();

Detach first so no new Flutter events enter a manager that is closing.

Further reading #

License #

Apache License 2.0. See LICENSE and NOTICE.

0
likes
160
points
266
downloads

Documentation

Documentation
API reference

Publisher

verified publisherarktelos.dev

Weekly Downloads

Flutter capture hooks and presentation integration for Ark Error Manager.

Homepage
Repository (GitLab)
View/report issues

Topics

#architecture #error-handling #flutter #observability

License

Apache-2.0 (license)

Dependencies

ark_error_manager, flutter

More

Packages that depend on ark_error_manager_flutter