@@ -33,6 +33,9 @@ const _pauseIsolatesOnStartFlag = 'pause_isolates_on_start';
3333/// closes before the new connection is established, preventing premature isolate destruction.
3434const _isolateDestructionGracePeriod = Duration (seconds: 15 );
3535
36+ /// Error message when no clients are available for hot reload/restart.
37+ const kNoClientsAvailable = 'No clients available.' ;
38+
3639/// Tracks hot reload responses from multiple browser windows/tabs.
3740class _HotReloadTracker {
3841 final String requestId;
@@ -117,6 +120,16 @@ class _ServiceExtensionTracker {
117120 }
118121}
119122
123+ /// Exception thrown when no browser clients are connected to DWDS.
124+ class NoClientsAvailableException implements Exception {
125+ final String message;
126+
127+ NoClientsAvailableException ._(this .message);
128+
129+ @override
130+ String toString () => 'NoClientsAvailableException: $message ' ;
131+ }
132+
120133/// WebSocket-based VM service proxy for web debugging.
121134class WebSocketProxyService extends ProxyService {
122135 final _logger = Logger ('WebSocketProxyService' );
@@ -504,6 +517,14 @@ class WebSocketProxyService extends ProxyService {
504517 await _performWebSocketHotReload ();
505518 _logger.info ('Hot reload completed successfully' );
506519 return _ReloadReportWithMetadata (success: true );
520+ } on NoClientsAvailableException catch (e) {
521+ // Throw RPC error with kIsolateCannotReload code when no browser clients are
522+ // connected.
523+ throw vm_service.RPCError (
524+ 'reloadSources' ,
525+ vm_service.RPCErrorKind .kIsolateCannotReload.code,
526+ 'Hot reload failed: ${e .message }' ,
527+ );
507528 } catch (e) {
508529 _logger.warning ('Hot reload failed: $e ' );
509530 return _ReloadReportWithMetadata (success: false , notices: [e.toString ()]);
@@ -518,6 +539,14 @@ class WebSocketProxyService extends ProxyService {
518539 await _performWebSocketHotRestart ();
519540 _logger.info ('Hot restart completed successfully' );
520541 return {'result' : vm_service.Success ().toJson ()};
542+ } on NoClientsAvailableException catch (e) {
543+ // Throw RPC error with kIsolateCannotReload code when no browser clients are
544+ // connected.
545+ throw vm_service.RPCError (
546+ 'hotRestart' ,
547+ vm_service.RPCErrorKind .kIsolateCannotReload.code,
548+ 'Hot restart failed: ${e .message }' ,
549+ );
521550 } catch (e) {
522551 _logger.warning ('Hot restart failed: $e ' );
523552 return {
@@ -611,7 +640,8 @@ class WebSocketProxyService extends ProxyService {
611640 });
612641
613642 if (clientCount == 0 ) {
614- throw StateError ('No clients available for hot reload' );
643+ _logger.warning (kNoClientsAvailable);
644+ throw NoClientsAvailableException ._(kNoClientsAvailable);
615645 }
616646
617647 // Create tracker for this hot reload request
@@ -671,7 +701,8 @@ class WebSocketProxyService extends ProxyService {
671701 });
672702
673703 if (clientCount == 0 ) {
674- throw StateError ('No clients available for hot restart' );
704+ _logger.warning (kNoClientsAvailable);
705+ throw NoClientsAvailableException ._(kNoClientsAvailable);
675706 }
676707
677708 // Create tracker for this hot restart request
@@ -737,8 +768,7 @@ class WebSocketProxyService extends ProxyService {
737768 final request = ServiceExtensionRequest .fromArgs (
738769 id: requestId,
739770 method: method,
740- args:
741- args != null ? Map <String , dynamic >.from (args) : < String , dynamic > {},
771+ args: < String , Object ? > {...? args},
742772 );
743773
744774 // Send the request and get the number of connected clients
0 commit comments