Skip to content

Conversation

jyameo
Copy link
Contributor

@jyameo jyameo commented Oct 15, 2025

This PR introduces graceful handling for scenarios where no browser clients are connected to DWDS during hot reload and hot restart operations. Previously, DWDS threw generic StateError exceptions that required Flutter Tools to parse error messages using brittle string matching. Now, a custom NoClientsAvailableException is thrown and caught, with structured error responses that include a noClientsAvailable boolean field in the JSON output. This enables type-safe error handling and eliminates the need for error string parsing. The changes affect the reloadSources and hotRestart methods in WebSocketProxyService, which now return success responses with metadata when no clients are available, treating this as a recoverable scenario rather than a fatal error.

Related to flutter/flutter#174791

Changes in Flutter tools (Child PR): flutter/flutter#177026

_logger.info('No clients available for hot restart');
return {
'result': {
'type': 'Success',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't feel right as this isn't a Success.

Realistically, we should be doing something like throwing an RPCError with an error code that package:vm_service forwards without modification. Right now, package:vm_service catches all exceptions and wraps them in RPCErrors with a kServerError code, but maybe we should update it to rethrow RPCError instances.

Another option would be to update the hotRestart extension to return ReloadReport as well so we can be consistent between hotReload and hotRestart.

Copy link
Contributor Author

@jyameo jyameo Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! This shouldn’t be treated as a success. I think returning a ReloadReport would be the better approach to keep things consistent and also add the field noClientsAvailable. For now, I’ve removed the type field since it’s not being used for this operation.

In another PR, we can refactor this to return a ReloadReport instead, that would also involve updating the Chrome path and Flutter tools as well, as they currently expect the existing format.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does that sound? @bkonyi

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually don't think we can remove the type property in the result without consequence. package:vm_service checks for this and, if it can't find the type, returns a Response by default. While I don't think anyone is checking for the Success object explicitly since there's no useful information attached to it, this could break things.

I think it's just worth updating the return type to be ReloadReport now and then updating Flutter to return the same when we roll this change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following our discussion I have made the changes to throw an RPC Error for this scenario which we catch in Flutter tools. PTAL

@bkonyi @srujzs

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I feel like this resurrects the original issue we had where we can't distinguish what the kServerError corresponds to, whereas if we had hot restart return a ReloadReport, we have that metadata in the report.

(also I'll be OOO tomorrow, so if you decide this is the right approach anyways, feel free to land it)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey Srujan, Ben sand I discussed this and decided that this approach to throw an RPCError would work better since changing hot restart to return a ReloadReport would also require modifying the Chrome path, which could introduce some breakage.

In Flutter tools, I check for the calling method and kServerError to distinguish that this is the specific scenario. We could technically add a new RPCErrorKind for this, but I’m not sure it’s really necessary.

Thoughts? @bkonyi

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we'd like to avoid using the generic kServerError, I think we can go ahead and use kIsolateCannotReload to indicate that the reload has failed.

Copy link
Contributor

@srujzs srujzs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks Jessy! I'm guessing we can't add a test in DWDS as it requires closing the browser or somehow disrupting the connection which is going to be manual and therefore requires something like the Flutter test runner.

@jyameo
Copy link
Contributor Author

jyameo commented Oct 15, 2025

Looks good, thanks Jessy! I'm guessing we can't add a test in DWDS as it requires closing the browser or somehow disrupting the connection which is going to be manual and therefore requires something like the Flutter test runner.

yes that's correct I have added a test in flutter tools for this scenario

@jyameo jyameo requested a review from bkonyi October 15, 2025 20:27
@jyameo jyameo requested a review from srujzs October 16, 2025 20:40
@jyameo jyameo requested a review from bkonyi October 17, 2025 14:18
Copy link
Collaborator

@bkonyi bkonyi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with one nit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants