Skip to content

dotnet watch: Mac Catalyst hot-reload agent WebSocket drops before the first edit; updates fail but watch reports "changes applied" #55488

Description

@horatiuvlad

Summary

On Mac Catalyst, dotnet watch run's hot-reload agent connects and negotiates full capabilities at app startup, then its WebSocket connection drops before the first edit arrives. Every subsequent update batch fails with No active WebSocket connection from the client, the session gives up (Further changes won't be applied to this process) — and dotnet watch still reports C# and Razor changes applied in 835ms, so the failure is invisible unless running with --verbose.

Two distinct problems:

  1. the agent's WebSocket connection does not survive from startup to the first edit, and there is no reconnect;
  2. dotnet watch reports success after every update in the batch failed.

Environment

macos-latest GitHub runner (arm64), .NET SDK 10.0.3xx, maui workload set 10.0.302 (i.e. including dotnet/macios#24664, so StartupHookSupport defaults to true in Debug and the agent genuinely loads). App: scaffolded MAUI-based Mac Catalyst app, net10.0-maccatalyst, Debug, DOTNET_USE_POLLING_FILE_WATCHER=1.

Launch is worked around via an explicit _AppBundleName override (without it dotnet run cannot start a Catalyst app at all when ApplicationTitle != AssemblyName; filed as dotnet/macios#26318).

Observed (verbose log, single session)

At startup:

dotnet watch : Hot reload session started.
dotnet watch : [App (net10.0-maccatalyst)] WebSocket client connected
dotnet watch : [App (net10.0-maccatalyst)] Capabilities: 'Baseline AddMethodToExistingType AddStaticFieldToExistingType NewTypeDefinition ChangeCustomAttributes AddInstanceFieldToExistingType GenericAddMethodToExistingType GenericUpdateMethod UpdateParameters GenericAddFieldToExistingType AddExplicitInterfaceImplementation'.
dotnet watch : [App (net10.0-maccatalyst)] WebSocket client disconnected

On the first (method-body-only) edit, ~1 minute later:

dotnet watch : File change: Update '.../MainPage.cs'.
dotnet watch : Hot reload capabilities: ... (full set)
dotnet watch : [App (net10.0-maccatalyst)] Sending update batch #0
dotnet watch : [App (net10.0-maccatalyst)] Update batch #0 failed with error: No active WebSocket connection from the client.
dotnet watch : [App (net10.0-maccatalyst)] Update batch #0 exception stack trace:    at Microsoft.DotNet.HotReload.WebSocketClientTransport.RequestHandler.WriteAsync(...)
dotnet watch : [App (net10.0-maccatalyst)] Further changes won't be applied to this process.
dotnet watch : [App (net10.0-maccatalyst)] Disposing agent websocket transport
dotnet watch : C# and Razor changes applied in 835ms.

Verified at runtime that nothing was applied: the edit injected a Console.WriteLine into a method the app executes every 10 seconds; the new output never appeared over 180s, and the process was not restarted either. Reproduced identically across two independent sessions (with and without an explicit MtouchInterpreter=all, which is the Debug default anyway).

Expected

Either the agent connection stays up for the lifetime of the process (or reconnects), or — failing that — dotnet watch reports the update as failed and falls back to its restart path, instead of printing changes applied.

The false success seems the more severe half: without --verbose the user sees a healthy hot-reload session that silently applies nothing.

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions