Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dotnet watch run completely broken for F# #44908

Open
isaacabraham opened this issue Nov 16, 2024 · 42 comments
Open

dotnet watch run completely broken for F# #44908

isaacabraham opened this issue Nov 16, 2024 · 42 comments
Labels
Area-Watch untriaged Request triage from a team member

Comments

@isaacabraham
Copy link

Describe the bug

Using dotnet watch run does not work for F# applications. It won't start the application at all.

This is the output I get:

PS D:\code\TodoService\src\app> dotnet watch run
dotnet watch 🔥 Hot reload enabled. For a list of supported edits, see https://aka.ms/dotnet/hot-reload.
  💡 Press "Ctrl + R" to restart.
Using launch settings from D:\code\TodoService\src\app\Properties\launchSettings.json...
dotnet watch ⏳ Waiting for a file to change before restarting dotnet...

At this point, the application should be running, but isn't. Notice how it is trying to use hot reload which doesn't support F#.

When I make a change to the application code (which should trigger a standard watch run restart), sure enough I get this:

dotnet watch ❌ System.InvalidOperationException: Cannot open project 'D:\code\TodoService\src\app\app.fsproj' because the file extension '.fsproj' is not associated with a language.
   at Microsoft.CodeAnalysis.MSBuild.DiagnosticReporter.Report(DiagnosticReportingMode mode, String message, Func`2 createException)
   at Microsoft.CodeAnalysis.MSBuild.ProjectFileExtensionRegistry.TryGetLanguageNameFromProjectPath(String projectFilePath, DiagnosticReportingMode mode, String& languageName)
   at Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.Worker.LoadProjectFileInfosAsync(String projectPath, DiagnosticReportingOptions reportingOptions, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.Worker.LoadProjectInfosFromPathAsync(String projectPath, DiagnosticReportingOptions reportingOptions, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.Worker.LoadAsync(CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.LoadProjectInfoAsync(String projectFilePath, ProjectMap projectMap, IProgress`1 progress, ILogger msbuildLogger, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.LoadProjectInfoAsync(String projectFilePath, ProjectMap projectMap, IProgress`1 progress, ILogger msbuildLogger, CancellationToken cancellationToken)
   at Microsoft.DotNet.Watcher.Tools.IncrementalMSBuildWorkspace.UpdateProjectConeAsync(String rootProjectPath, CancellationToken cancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.Program.RunAsync()
dotnet watch ❌ An unexpected error occurred

Fsproj is indeed associated with a language - F#. It's just that hot reload doesn't know about it. It's completely broken.

Using dotnet run works, thankfully:

PS D:\code\TodoService\src\app> dotnet run
Using launch settings from D:\code\TodoService\src\app\Properties\launchSettings.json...
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: D:\code\TodoService\src\app

To Reproduce

I have an F#9 project which uses the Web SDK. It doesn't use anything else really - standard nuget etc.

Further technical details

  • Include the output of dotnet --info
  • The IDE (VS / VS Code/ VS4Mac) you're running on, and its version
.NET SDK:
 Version:           9.0.100
 Commit:            59db016f11
 Workload version:  9.0.100-manifests.c6f19616
 MSBuild version:   17.12.7+5b8665660

Running on Win 11.

@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Watch untriaged Request triage from a team member labels Nov 16, 2024
@baronfel
Copy link
Member

cc @tmat

@forki
Copy link

forki commented Nov 16, 2024

Noticed that as well and I assumed I messed up my setup

@isaacabraham
Copy link
Author

This would be extremely undesirable to leave in for any period of time - F# web applications rely heavily on this (the entire SAFE Stack is built upon a watch mode for both client and server for example).

@forki
Copy link

forki commented Nov 16, 2024

Also dotnet aspire is broken for F# users.
/cc @davidfowl

@baronfel
Copy link
Member

Using the Roslyn MSBuild APIs directly likely won't work for any project type that is non-Roslyn. I'd expect watch for esproj for example to be broken similarly based on this stack.

@forki
Copy link

forki commented Nov 17, 2024

@vzarytovskii

@vzarytovskii
Copy link
Member

vzarytovskii commented Nov 17, 2024

@vzarytovskii

Nothing actionable for us here, unfortunately, Roslyn/watch team needs to fix it.

@vzarytovskii
Copy link
Member

Also, I assume --no-hot-reload still works? It should be automatically enabled for F# projects

@tmat
Copy link
Member

tmat commented Nov 18, 2024

Yes, a workaround is to pass --no-hot-reload.

@forki
Copy link

forki commented Nov 18, 2024

How is that a workaround?

@tmat
Copy link
Member

tmat commented Nov 18, 2024

@forki Passing --no-hot-reload makes dotnet-watch work as expected until a fix is available.

@vzarytovskii
Copy link
Member

vzarytovskii commented Nov 18, 2024

How is that a workaround?

Proper hot reload was never supported in F#. @tmat do you know what changed to default behaviour, so it's failing in F# now, did no-hot-reload become default in net8, and now is off-by-default in net9?

@forki
Copy link

forki commented Nov 18, 2024

Well it worked in fable. But yes for dotnet watch run, changes in fsproj or fs files did a recompile and restart. Which would be OK if this works properly again

@isaacabraham
Copy link
Author

How is that a workaround?

Proper hot reload was never supported in F#. @tmat do you know what changed to default behaviour, so it's failing in F# now, did no-hot-reload become default in net8, and now is off-by-default in net9?

Even if that were the case, it should only be on-by-default for C# projects - the rest of everything will break, and there's no need to enforce an extra cmdline parameter on everyone because of this.

@tmat
Copy link
Member

tmat commented Nov 19, 2024

@isaacabraham What about F# projects that have C# dependencies and vice versa? Would you expect Hot Reload work for C# code and trigger rebuild for changes in F# code?

@JordanMarr
Copy link

For anyone else affected by this issue, my workaround is to add the following file:

global.json

{
  "sdk": {
    "version": "8.0.100",
    "rollForward": "latestMinor",
    "allowPrerelease": false
  }
}

@isaacabraham
Copy link
Author

@isaacabraham What about F# projects that have C# dependencies and vice versa? Would you expect Hot Reload work for C# code and trigger rebuild for changes in F# code?

@tmat That would be nice. But either way you cannot have, by default, F# projects suddenly broken with .NET Watch i.e. a massive breaking change that has not been documented at all.

@isaacabraham
Copy link
Author

For anyone else affected by this issue, my workaround is to add the following file:

global.json

{
"sdk": {
"version": "8.0.100",
"rollForward": "latestMinor",
"allowPrerelease": false
}
}

IOW - don't use .NET 9?

I think the workaround to explicitly turn off hot reload is better but still extremely undesirable.

@JordanMarr
Copy link

JordanMarr commented Nov 23, 2024

For anyone else affected by this issue, my workaround is to add the following file:
global.json
{
"sdk": {
"version": "8.0.100",
"rollForward": "latestMinor",
"allowPrerelease": false
}
}

IOW - don't use .NET 9?

I think the workaround to explicitly turn off hot reload is better but still extremely undesirable.

I am in the middle of a very large project using a net8 F# web api.
I installed net9 - only for use with newer projects - which caused hot reload to stop working on my net8 project.
So in my case, adding the global.json file to lock to net8 was the right workaround.
 
Hot reload is important enough to me that even if I had already upgraded to net9, I would at least consider reverting to net8 to eliminate the massive inconvenience of manually restarting on every change.

@isaacabraham
Copy link
Author

That makes sense. I would suggest as a matter of course always having a global.json file - this is especially crucial on multi-person projects.

@pkese
Copy link

pkese commented Nov 23, 2024

Does anyone know what does 'Hot reload' feature do exactly, and how does C# work differently than F# in this regard?

BTW, there's an option to disable it on a per project basis, but I'm not sure if this only works for ASP.NET applications:
https://learn.microsoft.com/en-us/aspnet/core/test/hot-reload?view=aspnetcore-9.0#disable-hot-reload

@tmat
Copy link
Member

tmat commented Nov 24, 2024

No need to switch to .NET 8. You can pass --no-hot-reload to dotnet watch and .NET 9 version without fix behaves the same as .NET 8 for F# projects. The switch is only needed until the fix ships in .NET 9.

@mrange
Copy link

mrange commented Nov 24, 2024

No need to switch to .NET 8. You can pass --no-hot-reload to dotnet watch and .NET 9 version without fix behaves the same as .NET 8 for F# projects. The switch is only needed until the fix ships in .NET 9.

This workaround also seems to work for VB.NET.

@isaacabraham
Copy link
Author

No need to switch to .NET 8. You can pass --no-hot-reload to dotnet watch and .NET 9 version without fix behaves the same as .NET 8 for F# projects. The switch is only needed until the fix ships in .NET 9.

This workaround also seems to work for VB.NET.

That's right, this issue impacts all non-C# projects that work with MSBuild AFAIK.

@NatElkins
Copy link

Just want to chime in that I have also run into this issue (I guess every non-C# user will).

@channeladam
Copy link

channeladam commented Nov 28, 2024

I am having a similar issue with my C# only web app still targeting .NET 8.
dotnet watch was working fine with .NET 8 SDK, but is now broken with 9 SDK.

--no-hot-reload is working as a workaround.

When I say similar, I mean it hits part of the same stack trace...
.IncrementalMSBuildWorkspace.UpdateProjectConeAsync

dotnet watch ❌ System.FormatException: Input string was not in a correct format. Failure to parse near offset 193. Expected an ASCII digit.
   at System.Text.ValueStringBuilder.AppendFormatHelper(IFormatProvider provider, String format, ReadOnlySpan`1 args)
   at System.String.FormatHelper(IFormatProvider provider, String format, ReadOnlySpan`1 args)
   at System.String.Format(String format, Object[] args)
   at Microsoft.Extensions.Tools.Internal.MessageDescriptor.TryGetMessage(String prefix, Object[] args, String& message)
   at Microsoft.Extensions.Tools.Internal.ConsoleReporter.Report(MessageDescriptor descriptor, String prefix, Object[] args)
   at Microsoft.Extensions.Tools.Internal.IReporter.Report(MessageDescriptor descriptor, Object[] args)
   at Microsoft.Extensions.Tools.Internal.IReporter.Verbose(String message, String emoji)
   at Microsoft.DotNet.Watcher.Tools.IncrementalMSBuildWorkspace.<>c__DisplayClass6_0.<<ReportSolutionFilesAsync>g__InspectDocumentAsync|0>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.DotNet.Watcher.Tools.IncrementalMSBuildWorkspace.ReportSolutionFilesAsync(Solution solution, CancellationToken cancellationToken)
   at Microsoft.DotNet.Watcher.Tools.IncrementalMSBuildWorkspace.UpdateProjectConeAsync(String rootProjectPath, CancellationToken cancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.Program.RunAsync()
dotnet watch ❌ An unexpected error occurred

@fingers10
Copy link

I am having a similar issue with my C# only web app still targeting .NET 8. dotnet watch was working fine with .NET 8 SDK, but is now broken with 9 SDK.

--no-hot-reload is working as a workaround.

When I say similar, I mean it hits part of the same stack trace... .IncrementalMSBuildWorkspace.UpdateProjectConeAsync

dotnet watch ❌ System.FormatException: Input string was not in a correct format. Failure to parse near offset 193. Expected an ASCII digit.
   at System.Text.ValueStringBuilder.AppendFormatHelper(IFormatProvider provider, String format, ReadOnlySpan`1 args)
   at System.String.FormatHelper(IFormatProvider provider, String format, ReadOnlySpan`1 args)
   at System.String.Format(String format, Object[] args)
   at Microsoft.Extensions.Tools.Internal.MessageDescriptor.TryGetMessage(String prefix, Object[] args, String& message)
   at Microsoft.Extensions.Tools.Internal.ConsoleReporter.Report(MessageDescriptor descriptor, String prefix, Object[] args)
   at Microsoft.Extensions.Tools.Internal.IReporter.Report(MessageDescriptor descriptor, Object[] args)
   at Microsoft.Extensions.Tools.Internal.IReporter.Verbose(String message, String emoji)
   at Microsoft.DotNet.Watcher.Tools.IncrementalMSBuildWorkspace.<>c__DisplayClass6_0.<<ReportSolutionFilesAsync>g__InspectDocumentAsync|0>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.DotNet.Watcher.Tools.IncrementalMSBuildWorkspace.ReportSolutionFilesAsync(Solution solution, CancellationToken cancellationToken)
   at Microsoft.DotNet.Watcher.Tools.IncrementalMSBuildWorkspace.UpdateProjectConeAsync(String rootProjectPath, CancellationToken cancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.Program.RunAsync()
dotnet watch ❌ An unexpected error occurred

I'm facing exact same error in c#

@forki
Copy link

forki commented Dec 11, 2024

In the case of Aspire --no-hot-reload makes things even worse. Then a change in a subproject is making the whole apphost rebuilding and restarting services. It can't even open new ports and everything is broken.

@OnurGumus
Copy link

OnurGumus commented Dec 13, 2024

For me --no-hot-reload doesn't work at all. I get a different error message when I modify a static file in webroot

dotnet watch ❌ System.ArgumentNullException: Value cannot be null. (Parameter 'key')
   at System.Collections.Generic.Dictionary`2.FindValue(TKey key)
   at System.Collections.Generic.Dictionary`2.TryGetValue(TKey key, TValue& value)
   at Microsoft.DotNet.Watcher.Tools.StaticFileHandler.HandleFileChangesAsync(IReadOnlyList`1 files, CancellationToken cancellationToken)
   at Microsoft.DotNet.Watcher.DotNetWatcher.WatchAsync(CancellationToken cancellationToken)
   at Microsoft.DotNet.Watcher.DotNetWatcher.WatchAsync(CancellationToken cancellationToken)
   at Microsoft.DotNet.Watcher.Program.RunAsync()

Oh and this is reported here
#45183
So not F# related.

@tmat
Copy link
Member

tmat commented Dec 18, 2024

Fixed by #44928 in 9.0.1xx

@tmat tmat closed this as completed Dec 18, 2024
@halcwb
Copy link

halcwb commented Dec 22, 2024

I installed the sdk for the fix:

dotnet --info
.NET SDK:
Version: 9.0.101
Commit: eedb237
Workload version: 9.0.100-manifests.3068a692
MSBuild version: 17.12.12+1cce77968

Runtime Environment:
OS Name: Mac OS X
OS Version: 14.6
OS Platform: Darwin
RID: osx-arm64
Base Path: /usr/local/share/dotnet/sdk/9.0.101/

Unfortunately, I stil run into the 'fsproj' is not associated with a language error:

dotnet watch 🔥 Hot reload enabled. For a list of supported edits, see https://aka.ms/dotnet/hot-reload.
  💡 Press "Ctrl + R" to restart.
Hello from F#!
dotnet watch ⌚ [Server (net9.0)] Exited
dotnet watch ⏳ Waiting for a file to change before restarting dotnet...
dotnet watch ❌ System.InvalidOperationException: Cannot open project '/Users/halcwb/Development/halcwb/apps/PICEDashboard/src/Server/Server.fsproj' because the file extension '.fsproj' is not associated with a language.
   at Microsoft.CodeAnalysis.MSBuild.DiagnosticReporter.Report(DiagnosticReportingMode mode, String message, Func`2 createException)
   at Microsoft.CodeAnalysis.MSBuild.ProjectFileExtensionRegistry.TryGetLanguageNameFromProjectPath(String projectFilePath, DiagnosticReportingMode mode, String& languageName)
   at Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.Worker.LoadProjectFileInfosAsync(String projectPath, DiagnosticReportingOptions reportingOptions, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.Worker.LoadProjectInfosFromPathAsync(String projectPath, DiagnosticReportingOptions reportingOptions, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.Worker.LoadAsync(CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.LoadProjectInfoAsync(String projectFilePath, ProjectMap projectMap, IProgress`1 progress, ILogger msbuildLogger, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.LoadProjectInfoAsync(String projectFilePath, ProjectMap projectMap, IProgress`1 progress, ILogger msbuildLogger, CancellationToken cancellationToken)
   at Microsoft.DotNet.Watcher.Tools.IncrementalMSBuildWorkspace.UpdateProjectConeAsync(String rootProjectPath, CancellationToken cancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.HotReloadDotNetWatcher.WatchAsync(CancellationToken shutdownCancellationToken)
   at Microsoft.DotNet.Watcher.Program.RunAsync()
dotnet watch ❌ An unexpected error occurred

@MaxGripe
Copy link

@tmat Could you please open this? Since it's not fixed?

@halcwb
Copy link

halcwb commented Dec 22, 2024

@tmat Could you please open this? Since it's not fixed?

I don't have permissions to reopen the issue, that's why I created the new issue with reference to the old one.

@baronfel
Copy link
Member

This should be fixed in January's servicing release - the fix was made but due to slower release schedules over the holiday season it won't be released until then. There's nothing wrong or out of the ordinary with this - many fixes across the CLI are in the same bucket.

@baronfel baronfel marked this as a duplicate of #45610 Dec 22, 2024
@halcwb
Copy link

halcwb commented Dec 22, 2024

This should be fixed in January's servicing release - the fix was made but due to slower release schedules over the holiday season it won't be released until then. There's nothing wrong or out of the ordinary with this - many fixes across the CLI are in the same bucket.

@baronfel : sorry about that, thought this was fixed in the release I was on. Enjoy the holidays!

@baronfel
Copy link
Member

No problem at all! The release schedule isn't the most transparent thing in the world, I know :( In any case, happy holidays!

@enriquein
Copy link

Here to report that this is still a problem in the latest servicing update released on January 14.

dotnet watch --version returned 9.0.102-servicing.24611.3+cb83cd4923f0973ae11dfb5602737493bf165210.

Uninstalling the dotnet 9 SDK for the time being until this can get resolved.

@forki
Copy link

forki commented Feb 14, 2025

@baronfel with 9.0.200 it's still broken. This issue should be reopened

@baronfel
Copy link
Member

@forki does the repro from the initial report still trigger the issue, or is it a different scenario?

@tmat can you look again please?

@baronfel baronfel reopened this Feb 14, 2025
@forki
Copy link

forki commented Feb 14, 2025

we're using 9.0.200 with .NET aspire. It's the same error message as above

Image

@tmat
Copy link
Member

tmat commented Feb 14, 2025

@forki

Image

This is a warning from msbuild that we won't be able to reload F# projects. Reloading F# is currently not supported in Aspire apps.
 

@baronfel with 9.0.200 it's still broken. This issue should be reopened

Can you elaborate on what's broken? Can you share verbose output?

@halcwb
Copy link

halcwb commented Feb 16, 2025

@forki, @tmat , @isaacabraham

I use this feature mainly with the SAFE stack. And with the 9.0.200 version it seems fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Watch untriaged Request triage from a team member
Projects
None yet
Development

No branches or pull requests