Problem Statement
How do you handle errors in Streams? Explain error handling strategies and best practices.
Explanation
Add errors to streams using controller.addError(error) or by throwing in async* generators - thrown errors are caught and added as stream errors. When listening to streams with listen(), provide onError callback to handle errors: stream.listen(onData, onError: (error) { /* handle */ }). In StreamBuilder, check snapshot.hasError and display error UI with details from snapshot.error.
Use handleError() to catch and handle stream errors in the stream pipeline, deciding whether to continue or stop the stream. HandleError can transform errors, suppress them, or perform side effects. Use transform() with StreamTransformer for complex error handling logic, catching errors, recovering, or emitting default values. For critical streams that shouldn't stop on errors, catch errors in handleError and continue the stream.
Set cancelOnError parameter when listening to control whether subscription cancels on first error - default true cancels, false continues receiving events after errors. For broadcast streams with multiple listeners, errors are sent to all listeners, but each listener's cancelOnError setting is independent. This allows different error handling strategies for different consumers.
Best practices include always providing error handlers preventing uncaught stream errors that can crash apps, logging errors for debugging and monitoring, recovering gracefully with fallback values or retry logic, and using specific error types for different failure scenarios enabling appropriate handling. For user-facing streams, always handle errors in UI showing appropriate error messages. Test error scenarios ensuring your error handling works correctly under various failure conditions.

