Summary
The six FSharp.Core HintPath entries in the solution are split between the lib/netstandard2.0 and
lib/netstandard2.1 flavours of the FSharp.Core.11.0.100 package. The netstandard2.1 flavour references
netstandard, Version=2.1.0.0, an identity that does not exist for .NET Framework on any machine, so that
copy is unloadable wherever it is deployed. Which flavour lands in any given output directory is
last-writer-wins build-order nondeterminism, so a project can flip between working and broken across a
rebuild with no source change.
Environment
- OS/version: Windows 11 Pro 10.0.26200, .NET Framework 4.8.1 (net481)
- Python version: not applicable
- Command/flags used:
msbuild TaskMaster.sln /t:Rebuild /m /p:Configuration=Debug "/p:Platform=Any CPU"
- Data source or fixture:
packages/FSharp.Core.11.0.100, which ships both lib/netstandard2.0 and lib/netstandard2.1
Steps to Reproduce
- Rebuild the solution.
- Create a child
AppDomain whose ApplicationBase is QuickFiler.Test/bin/Debug and whose
ConfigurationFile is QuickFiler.Test.dll.config.
- From inside that domain, load
Deedle.dll from the same directory and invoke
Deedle.Frame.FromRecords<T>(IEnumerable<T>) over a one-element sequence of any record type.
- Repeat with
ApplicationBase set to TaskMaster.Test/bin/Debug.
Expected Behavior
Both directories deploy the same, loadable FSharp.Core, so the Deedle call behaves identically in each and
no output directory depends on build ordering for correctness.
Actual Behavior
Rooted at QuickFiler.Test/bin/Debug the call raises the production chain; rooted at
TaskMaster.Test/bin/Debug it returns a Frame normally.
TypeInitializationException [Deedle.Reflection]
---> TypeInitializationException [<StartupCode$Deedle>.$FrameUtils]
---> FileNotFoundException [netstandard, Version=2.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51]
Logs / Screenshots
Measured HintPath split, by file and line:
| Project file |
Line |
Flavour |
netstandard reference |
QuickFiler/QuickFiler.csproj |
52 |
lib/netstandard2.1 |
2.1.0.0 |
QuickFiler.Test/QuickFiler.Test.csproj |
259 |
lib/netstandard2.1 |
2.1.0.0 |
ToDoModel/ToDoModel.csproj |
42 |
lib/netstandard2.1 |
2.1.0.0 |
UtilitiesCS/UtilitiesCS.csproj |
70 |
lib/netstandard2.0 |
2.0.0.0 |
UtilitiesCS.Test/UtilitiesCS.Test.csproj |
598 |
lib/netstandard2.0 |
2.0.0.0 |
ToDoModel.Test/ToDoModel.Test.csproj |
96 |
lib/netstandard2.0 |
2.0.0.0 |
netstandard 2.0.0.0 resolves from the GAC; netstandard 2.1.0.0 does not exist for .NET Framework.
Deedle.dll 3.0.0.0 references netstandard 2.0.0.0 and FSharp.Core 4.5.0.0, so Deedle is never the
source of the 2.1.0.0 request. FSharp.Core is.
Impact / Severity
TaskMaster.csproj lines 501 and 517 reference QuickFiler and ToDoModel, both netstandard2.1, alongside
four netstandard2.0 projects. The add-in output directory currently receives the netstandard2.0 copy, which
is why the reported production failure does not reproduce there today. That is build-order luck, not
correctness: the add-in can flip back into the failing state on any rebuild without a source change. The
originally reported failure in issue #879 is evidence that it has already been in that state once.
Source
From: docs/features/potential/2026-09-14-fsharp-core-hintpath-netstandard21-skew.md
Summary
The six
FSharp.CoreHintPathentries in the solution are split between thelib/netstandard2.0andlib/netstandard2.1flavours of theFSharp.Core.11.0.100package. The netstandard2.1 flavour referencesnetstandard, Version=2.1.0.0, an identity that does not exist for .NET Framework on any machine, so thatcopy is unloadable wherever it is deployed. Which flavour lands in any given output directory is
last-writer-wins build-order nondeterminism, so a project can flip between working and broken across a
rebuild with no source change.
Environment
msbuild TaskMaster.sln /t:Rebuild /m /p:Configuration=Debug "/p:Platform=Any CPU"packages/FSharp.Core.11.0.100, which ships bothlib/netstandard2.0andlib/netstandard2.1Steps to Reproduce
AppDomainwhoseApplicationBaseisQuickFiler.Test/bin/Debugand whoseConfigurationFileisQuickFiler.Test.dll.config.Deedle.dllfrom the same directory and invokeDeedle.Frame.FromRecords<T>(IEnumerable<T>)over a one-element sequence of any record type.ApplicationBaseset toTaskMaster.Test/bin/Debug.Expected Behavior
Both directories deploy the same, loadable
FSharp.Core, so the Deedle call behaves identically in each andno output directory depends on build ordering for correctness.
Actual Behavior
Rooted at
QuickFiler.Test/bin/Debugthe call raises the production chain; rooted atTaskMaster.Test/bin/Debugit returns aFramenormally.Logs / Screenshots
Measured
HintPathsplit, by file and line:QuickFiler/QuickFiler.csprojlib/netstandard2.1QuickFiler.Test/QuickFiler.Test.csprojlib/netstandard2.1ToDoModel/ToDoModel.csprojlib/netstandard2.1UtilitiesCS/UtilitiesCS.csprojlib/netstandard2.0UtilitiesCS.Test/UtilitiesCS.Test.csprojlib/netstandard2.0ToDoModel.Test/ToDoModel.Test.csprojlib/netstandard2.0netstandard 2.0.0.0resolves from the GAC;netstandard 2.1.0.0does not exist for .NET Framework.Deedle.dll3.0.0.0 referencesnetstandard 2.0.0.0andFSharp.Core 4.5.0.0, so Deedle is never thesource of the 2.1.0.0 request.
FSharp.Coreis.Impact / Severity
TaskMaster.csprojlines 501 and 517 referenceQuickFilerandToDoModel, both netstandard2.1, alongsidefour netstandard2.0 projects. The add-in output directory currently receives the netstandard2.0 copy, which
is why the reported production failure does not reproduce there today. That is build-order luck, not
correctness: the add-in can flip back into the failing state on any rebuild without a source change. The
originally reported failure in issue #879 is evidence that it has already been in that state once.
Source
From: docs/features/potential/2026-09-14-fsharp-core-hintpath-netstandard21-skew.md