diff --git a/packages/common_client/lib/src/data_sources/streaming_data_source.dart b/packages/common_client/lib/src/data_sources/streaming_data_source.dart index 692782a8..f3e5cb43 100644 --- a/packages/common_client/lib/src/data_sources/streaming_data_source.dart +++ b/packages/common_client/lib/src/data_sources/streaming_data_source.dart @@ -207,9 +207,11 @@ final class StreamingDataSource implements DataSource { _permanentShutdown = true; _logger.error( 'Encountered an unrecoverable error: "$err", Shutting down.'); - stop(); + // The event must be added before calling stop, because stop closes + // the controller and adding an event after that throws a StateError. _dataController.sink.add(StatusEvent(ErrorKind.unknown, null, 'Encountered unrecoverable error streaming')); + stop(); }); } diff --git a/packages/common_client/test/data_sources/streaming_data_source_test.dart b/packages/common_client/test/data_sources/streaming_data_source_test.dart index 8289457b..dc09068b 100644 --- a/packages/common_client/test/data_sources/streaming_data_source_test.dart +++ b/packages/common_client/test/data_sources/streaming_data_source_test.dart @@ -504,6 +504,28 @@ void main() { }); }); + group('stream error handling', () { + test( + 'it emits a status event without throwing when the stream reports an ' + 'unrecoverable error', () async { + final controller = StreamController(); + final (dataSource, _, statusManager) = + makeDataSourceForTest(controller.stream); + + final statusChange = expectLater( + statusManager.changes, + emits(predicate((status) => + status.lastError?.kind == ErrorKind.unknown && + status.lastError?.message == + 'Encountered unrecoverable error streaming'))); + + dataSource.start(); + controller.sink.addError(Exception('Unable to make request')); + + await statusChange; + }); + }); + group('environment ID from the stream connection', () { test('it uses the environment ID response header', () async { final controller = StreamController();