ark_error_manager_flutter 1.0.0
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.onErrorreceives failures caught by Flutter framework callbacks, including build, layout, paint, and explicitFlutterError.reportErrorcalls;PlatformDispatcher.onErrorreceives 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
attachon the same binding is idempotent; - attaching a different binding while one is active throws
StateError; detachrestores handlers that existed beforeattach;- a handler installed by a later external owner is never overwritten during detach;
isAttachedexposes 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_flutterreports unhandled runtime failures throughFlutterError.reportError;ark_di_flutterforwards unhandled scope-close failures to the owning Zone;usecase_forge_flutterreports 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 #
- Bootstrap and ownership
- Flutter hook behavior
- Runnable example
- Core architecture
- Core security model
- API reference
- Issue tracker