Tutorials
Build a pure-Dart error boundary
Configure assessment, bounded context, reporting, a root Zone, and controlled shutdown.
Build a pure-Dart error boundary
The example simulates an unhandled asynchronous failure in a catalog worker. The application classifies it as an integration outage, attaches two bounded request facts, sanitizes the report, writes it through a development Reporter, and waits for accepted work before shutdown.
The failing service never receives ErrorManager. Its uncaught error reaches the Zone already owned by the application.
Install the package
dart pub add ark_error_manager:^0.1.0-dev.1
Describe the runtime
const ErrorRuntimeEnvironment environment = ErrorRuntimeEnvironment(
buildMode: ErrorBuildMode.release,
deployment: ErrorDeploymentEnvironment.production,
application: ErrorApplicationInfo(
name: 'Catalog worker',
version: '1.4.0',
buildNumber: '87',
),
);
Build mode and deployment are separate: a release binary can run against staging, and a profile build can use production services.
Classify one application error
final class ServiceUnavailableClassifier
extends TypedErrorClassifier<ServiceUnavailableException> {
const ServiceUnavailableClassifier();
@override
ErrorAssessment classifyError(
ServiceUnavailableException error,
ErrorOccurrence occurrence,
ErrorRuntimeEnvironment environment,
) => const ErrorAssessment(
category: ErrorCategory.integration,
severity: ErrorSeverity.degraded,
);
}
Add bounded diagnostic context
final class RequestContextProvider implements ErrorContextProvider {
const RequestContextProvider();
@override
ErrorContextSection collect(
ErrorOccurrence occurrence,
ErrorRuntimeEnvironment environment,
) => ErrorContextSection(
name: 'request',
fields: <String, Object?>{
'method': 'GET',
'endpoint': '/catalog',
},
);
}
Context is intentionally small. It does not include headers, request bodies, credentials, or complete application state.
Create the manager
final ErrorManager manager = ErrorManager(
configuration: ErrorManagerConfiguration(
environment: environment,
classifiers: const <ErrorClassifier>[
ServiceUnavailableClassifier(),
],
contextProviders: const <ErrorContextProvider>[
RequestContextProvider(),
],
reporters: const <ErrorReporter>[
DeveloperLogErrorReporter(name: 'catalog.worker'),
],
),
);
The built-in fallback still handles every error not supported by the custom classifier.
Connect the application-owned Zone
final captured = Completer<void>();
runZonedGuarded(
() {
scheduleMicrotask(() {
throw const ServiceUnavailableException('catalog');
});
},
(error, stackTrace) {
manager.onUncaughtZoneError(error, stackTrace);
captured.complete();
},
);
await captured.future;
The package does not create the Zone. The application retains control over zoneValues, ZoneSpecification, and nested boundaries.
Close a controlled host
await manager.flush();
await manager.close();
After close, the manager cannot be reused.
Follow the incident through the pipeline
- The Zone creates
ErrorOccurrencewithErrorCaptureSource.zone. ServiceUnavailableClassifierproduces integration/degraded assessment.RequestContextProvideradds only method and endpoint.- The configured policy decides whether to report, present, or recover.
- The Sanitizer creates a separate
ErrorReport. DeveloperLogErrorReporterreceives the report, never the raw Incident.flushproves that all accepted work finished beforeclose.
Run the complete linked example. Then replace the development Reporter only after reading the Security section and defining transport, retention, access, and deletion rules for the destination.