Oxpecker fable plugin not working with fable 4.25.0+
When I'm trying to run command from any of the Oxpecker.Solid projects after updating from 4.24 to 4.25:
dotnet fable --noCache
I get the error
Loaded Oxpecker.Solid.SolidComponentAttribute from ..\..\src\Oxpecker.Solid.FablePlugin\bin\Debug\net6.0\Oxpecker.Solid.FablePlugin.dll
Started Fable compilation...
Compiled 12/12: src\Components\TodoList.fs
Fable compilation finished in 4006ms
Unhandled exception. System.IO.FileNotFoundException: Could not load file or assembly 'FSharp.Core, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
File name: 'FSharp.Core, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
at System.ModuleHandle.ResolveType(QCallModule module, Int32 typeToken, IntPtr* typeInstArgs, Int32 typeInstCount, IntPtr* methodInstArgs, Int32 methodInstCount, ObjectHandleOnStack type)
at System.ModuleHandle.ResolveTypeHandle(Int32 typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
at System.Reflection.RuntimeModule.ResolveType(Int32 metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
at System.Reflection.CustomAttribute.FilterCustomAttributeRecord(MetadataToken caCtorToken, MetadataImport& scope, RuntimeModule decoratedModule, MetadataToken decoratedToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder`1& derivedAttributes, RuntimeType& attributeType, IRuntimeMethodInfo& ctorWithParameters, Boolean& isVarArg)
at System.Reflection.CustomAttribute.IsCustomAttributeDefined(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, RuntimeType attributeFilterType, Int32 attributeCtorToken, Boolean mustBeInheritable)
at System.Reflection.CustomAttribute.IsDefined(RuntimeType type, RuntimeType caType, Boolean inherit)
at System.RuntimeType.IsDefined(Type attributeType, Boolean inherit)
at System.Diagnostics.StackTrace.ToString(TraceFormat traceFormat, StringBuilder sb)
at System.Diagnostics.StackTrace.ToString(TraceFormat traceFormat)
at System.Exception.get_StackTrace()
at [email protected](FSharpResult`2 _arg3) in /home/mmangel/Workspaces/Github/fable-compiler/Fable/fable4/src/Fable.Cli/Main.fs:line 1128
at [email protected](Tuple`2 _arg2) in /home/mmangel/Workspaces/Github/fable-compiler/Fable/fable4/src/Fable.Cli/Main.fs:line 1116
at Microsoft.FSharp.Control.AsyncPrimitives.CallThenInvokeNoHijackCheck[a,b](AsyncActivation`1 ctxt, b result1, FSharpFunc`2 userCode) in /home/dev/Projects/fsharp/src/FSharp.Core/async.fs:line 528
at Microsoft.FSharp.Control.AsyncPrimitives.PostOrQueueWithTrampoline@932.Invoke(Unit unitVar0) in /home/dev/Projects/fsharp/src/FSharp.Core/async.fs:line 932
at Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc`2 firstAction) in /home/dev/Projects/fsharp/src/FSharp.Core/async.fs:line 112
--- End of stack trace from previous location ---
at Microsoft.FSharp.Control.AsyncResult`1.Commit() in /home/dev/Projects/fsharp/src/FSharp.Core/async.fs:line 454
at Microsoft.FSharp.Control.AsyncPrimitives.QueueAsyncAndWaitForResultSynchronously[a](CancellationToken token, FSharpAsync`1 computation, FSharpOption`1 timeout) in /home/dev/Projects/fsharp/src/FSharp.Core/async.fs:line 1139
at Microsoft.FSharp.Control.AsyncPrimitives.RunSynchronously[T](CancellationToken cancellationToken, FSharpAsync`1 computation, FSharpOption`1 timeout) in /home/dev/Projects/fsharp/src/FSharp.Core/async.fs:line 1166
at Microsoft.FSharp.Control.FSharpAsync.RunSynchronously[T](FSharpAsync`1 computation, FSharpOption`1 timeout, FSharpOption`1 cancellationToken) in /home/dev/Projects/fsharp/src/FSharp.Core/async.fs:line 1515
at [email protected](Unit _arg5) in /home/mmangel/Workspaces/Github/fable-compiler/Fable/fable4/src/Fable.Cli/Entry.fs:line 391
at [email protected](Tuple`2 _arg2) in /home/mmangel/Workspaces/Github/fable-compiler/Fable/fable4/src/Fable.Cli/Entry.fs:line 523
at Fable.Cli.Entry.main(String[] argv) in /home/mmangel/Workspaces/Github/fable-compiler/Fable/fable4/src/Fable.Cli/Entry.fs:line 515
To reproduce - download Oxpecker repository
- Go to this folder https://github.com/Lanayx/Oxpecker/tree/main/examples/EmptySolid
- Run
dotnet tool update fable - Observe fable build fails
Basically just reiterating issue https://github.com/Lanayx/Oxpecker/issues/77
I don't know where the problem can be coming from because the only impactful commits between the 2 version is:
https://github.com/fable-compiler/Fable/commit/ae2463bfa37a7a79d0ca90198eda619af7eacc6e
Some crazy thoughts:
- Stacktrace starts from
FSharpAsync.RunSynchronouslywhich was removed in 4.25 that might or might not be an issue - Next location has
System.Exception.get_StackTrace()in the middle, so it might be that some exception occured and then another exception was thrown during stacktrace collection that overrode original one. - Global json change is also suspicious
We can eliminate the first one in theory because
- Stacktrace starts from
FSharpAsync.RunSynchronouslywhich was removed in 4.25 that might or might not be an issue
The changes regarding RunSynchronously are Fable related, if you use RunSynchronously in your F# code then at compilation Fable is going to generate an error at compilation instead of generating something like Async.runSynchronously in your JavaScript which would fails at runtime
Here what is failing is the Fable compiler running in .NET not its compilation result
It seems that Fable 4.25.0 may have .NET 9 compatibility issues. It ships with FSharp.Core 8.0.200-dev but .NET 9 expects FSharp.Core 9.0.0.0, causing assembly loading failures.
The fix already exists in main branch (commit 418fb1fdc). Recommend fix is e.g. releasing Fable 4.26.0 with the F# 9.0 FCS updates backported.
I have tested this locally and can reproduce the build error with 4.25.0. The error is gone when cherry picking 418fb1fdc and making a new build.
What I did to test:
# In Fable
git checkout -b release/4.26.0 4.25.0
git cherry-pick 418fb1fdc
# Resolve conflicts (target framework, version)
dotnet pack src/Fable.Cli/Fable.Cli.fsproj -c Release -o ./local-packages
dotnet tool uninstall -g fable
dotnet tool install -g fable --version 4.25.0-fixed --add-source ./local-packages
# In Oxpecker
fable watch --exclude Oxpecker.Solid.FablePlugin --noCache --extension .jsx --run vite
# This works on my machine. Doing the same without the cherry-pick, fails
Thanks for the investigation @dbrattli
I am working on making a PR to fix the issue, this is a bit tricky because I also need to revert some improvements which were also made in that commit for Fable 5 only. But that's should be do-able :)
Tips: In case you want to use a local version of Fable you can also use ./build.sh package to a create a local package. It will give you a package that you can install on top of any existing Fable version no need for manual uninstall (because the version will always be higher)
Local packages created.
Use the following commands to install them:
- Fable.Cli: dotnet tool update fable --version 4.999.0-local-build-20250713-18613 --add-source /home/mmangel/Workspaces/Github/fable-compiler/Fable/fable4/temp/packages
- Fable.Core: dotnet add package Fable.Core --version 4.999.0-local-build-20250713-18613 --source /home/mmangel/Workspaces/Github/fable-compiler/Fable/fable4/temp/packages
@Lanayx Fable 4.26.0 should fix the issue
@MangelMaxime Unfortunately, is still doesn't work with Oxpecker.Solid plugin
Could not scan C:/Users/DavidFaivre/.nuget/packages/oxpecker.solid.fableplugin/0.7.0/lib/net6.0/Oxpecker.Solid.FablePlugin.dll for Fable plugins, skipping this assembly. Original error: The exception has been reported. This intern
al exception should now be caught at an error recovery point on the stack. Original message: The type 'AssemblyCompanyAttribute' is required here and is unavailable. You must add a reference to assembly 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.)
@Lanayx Does it work with the EmptySolid from Oxpecker repo directly?
If yes, could it be that a new release of the plugin is needed to update its dependencies ?
@MangelMaxime I reproduced the issue in clean folder downloaded from github as zip file, however didn't reproduce in a repo folder, which is pretty weird. I'll try to dig deeper tomorrow morning.
@MangelMaxime Just verified several times in clean folders that EmptySolid doesn't work neither with plugin built from sources (develop branch) nor downloaded from nuget (main branch) because of the aforementioned error. In the repo is didn't reproduce first, but after git clean -xfd it reproduced there as well.
Follow up of #4179, I decided to unlist Fable 4.26.0 because like @ncave pointed Fable 5 is the version that is made to work properly with F# 9 and .NET 9.0.
If Fable 4.24.0 works, it should means that something in #4106 broke it.
Outside of the changes in #4106 something that also changed compared to others release.
Is that instead of creating the release from the DevContainer because I was on a Mac, I am now using Linux directly on my machine which is probably why I needed to update the global.json as I had a different version of .NET installed on my machine.
I will see if using the dev container to create a local package fix the issue reported
@MangelMaxime I've decided to try Fable 5 with .NET 10 and it still fails for me with a similar error
Fable compilation finished in 3740ms
Unhandled exception. System.IO.FileNotFoundException: Could not load file or assembly 'FSharp.Core, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
File name: 'FSharp.Core, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
at System.ModuleHandle.ResolveType(QCallModule module, Int32 typeToken, IntPtr* typeInstArgs, Int32 typeInstCount, IntPtr* methodInstArgs, Int32 methodInstCount, ObjectHandleOnStack type)
at System.ModuleHandle.ResolveTypeHandle(Int32 typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
at System.Reflection.RuntimeModule.ResolveType(Int32 metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
at System.Reflection.CustomAttribute.FilterCustomAttributeRecord(MetadataToken caCtorToken, MetadataImport& scope, RuntimeModule decoratedModule, MetadataToken decoratedToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder`1& derivedAttributes, RuntimeType& attributeType, IRuntimeMethodInfo& ctorWithParameters, Boolean& isVarArg)
at System.Reflection.CustomAttribute.IsCustomAttributeDefined(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, RuntimeType attributeFilterType, Int32 attributeCtorToken, Boolean mustBeInheritable)
at System.Reflection.CustomAttribute.IsDefined(RuntimeType type, RuntimeType caType, Boolean inherit)
at System.Diagnostics.StackTrace.ToString(TraceFormat traceFormat, StringBuilder sb)
at System.Diagnostics.StackTrace.ToString(TraceFormat traceFormat)
at System.Exception.get_StackTrace()
at [email protected](FSharpResult`2 _arg3) in /home/mmangel/Workspaces/Github/fable-compiler/Fable/main/src/Fable.Cli/Main.fs:line 1139
at [email protected](Tuple`2 _arg2) in /home/mmangel/Workspaces/Github/fable-compiler/Fable/main/src/Fable.Cli/Main.fs:line 1127
at Microsoft.FSharp.Control.AsyncPrimitives.CallThenInvokeNoHijackCheck[a,b](AsyncActivation`1 ctxt, b result1, FSharpFunc`2 userCode) in /home/dev/Projects/fsharp/src/FSharp.Core/async.fs:line 528
at Microsoft.FSharp.Control.AsyncPrimitives.PostOrQueueWithTrampoline@932.Invoke(Unit unitVar0) in /home/dev/Projects/fsharp/src/FSharp.Core/async.fs:line 932
at Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc`2 firstAction) in /home/dev/Projects/fsharp/src/FSharp.Core/async.fs:line 112
--- End of stack trace from previous location ---
at Microsoft.FSharp.Control.AsyncResult`1.Commit() in /home/dev/Projects/fsharp/src/FSharp.Core/async.fs:line 454
at Microsoft.FSharp.Control.AsyncPrimitives.QueueAsyncAndWaitForResultSynchronously[a](CancellationToken token, FSharpAsync`1 computation, FSharpOption`1 timeout) in /home/dev/Projects/fsharp/src/FSharp.Core/async.fs:line 1139
at Microsoft.FSharp.Control.AsyncPrimitives.RunSynchronously[T](CancellationToken cancellationToken, FSharpAsync`1 computation, FSharpOption`1 timeout) in /home/dev/Projects/fsharp/src/FSharp.Core/async.fs:line 1166
at Microsoft.FSharp.Control.FSharpAsync.RunSynchronously[T](FSharpAsync`1 computation, FSharpOption`1 timeout, FSharpOption`1 cancellationToken) in /home/dev/Projects/fsharp/src/FSharp.Core/async.fs:line 1515
at [email protected](Unit unitVar0) in /home/mmangel/Workspaces/Github/fable-compiler/Fable/main/src/Fable.Cli/Entry.fs:line 391
at [email protected](Unit _arg5) in /home/mmangel/Workspaces/Github/fable-compiler/Fable/main/src/Fable.Cli/Entry.fs:line 398
at [email protected](Tuple`2 _arg2) in /home/mmangel/Workspaces/Github/fable-compiler/Fable/main/src/Fable.Cli/Entry.fs:line 540
at Fable.Cli.Entry.main(String[] argv) in /home/mmangel/Workspaces/Github/fable-compiler/Fable/main/src/Fable.Cli/Entry.fs:line 532
But this gave me the idea. It looks like the issue lies in combination of SDK and fable tool:
.NET SDK 8:
Fable 4.24 works Fable 4.25+ works Fable 5 works
.NET SDK 9:
Fable 4.24 works Fable 4.25+ errors! Fable 5 works
.NET SDK 10:
Fable 4.24 errors! Fable 4.25-4.27 errors! Fable 4.28 hangs! (this is the worst case) Fable 5 errors!
Hope this helps to understand the issue! I was running my tests on even simpler project by executing
dotnet fable --noCache --exclude Oxpecker.Solid.FablePlugin --extension .jsx
@Freymaurer Did you see a similar issue when working on Feliz plugins ?
Hey! Feliz is still set to .net8.0 so i can confirm that fable5 works with .net8.0.
I got the Empty Solid example working with the latest net10 and fable 5 .
<PackageReference Include="Oxpecker.Solid" Version="0.8.1" />
global.json:
{
"sdk": {
"version": "10.0.100",
"rollForward": "latestMinor"
}
}
dotnet-tools.json:
fable 4.24: ✅
fable 4.25: ❌ FileNotFoundException: Could not load file or assembly 'FSharp.Core, Version=9.0.0.0
fable 4.26: ✅
fable 4.27: ❌ FileNotFoundException: Could not load file or assembly 'FSharp.Core, Version=9.0.0.0
fable 4.28: ❌ just hangs after build succeded in 0.6s, Vite doesn't start.
.
.
.
fable 5.0.0-alpha.16: ✅
fable 5.0.0-alpha.17: ✅
fable 5.0.0-alpha.18: ✅
fable 5.0.0-alpha.19: ✅
@Lanayx does it work for you too with 5.0.0-alpha.19 ?
@goswinr it does work with 5.0.0-alpha.19 and 5.0.0-alpha.18! It doesn't work with 5.0.0-alpha.17 and below. And actually I was hoping for it to work because of this change. So, it looks like there is an implicit dependency on the FSharp.Core version bundled in Fable.Cli - it should match the SDK version the end user has installed.