docfx
docfx copied to clipboard
[Bug] .NET API bug: duplicate key in GenerateNestedTocStructure
Describe the bug My docfx build started failing because of a duplicate dictionary key error when generating a nested ToC structure. This started happening after I updated PolySharp in my project to 1.14.0.
To Reproduce
git clone https://github.com/sliekens/gw2sdk.git
cd gw2sdk
git reset --hard c62c6f5167b6dbee83dbc73b1bf6d1a414fa945d
git clean -df
dotnet tool restore
dotnet docfx
Expected behavior No crash
Context (please complete the following information):
-
OS: Debian 12
-
Docfx version: 2.74.1
-
.NET version: .NET 8.0.100
-
docfx.json
config
{
"metadata": [
{
"src": [
{
"src": "GW2SDK",
"files": [
"GW2SDK.csproj"
]
}
],
"dest": "docs/api",
"outputFormat": "mref",
"includePrivateMembers": false,
"disableGitFeatures": false,
"disableDefaultFilter": false,
"noRestore": false,
"namespaceLayout": "nested",
"memberLayout": "separatePages",
"enumSortOrder": "declaringOrder",
"allowCompilationErrors": false
}
],
"build": {
"content": [
{
"src": "docs",
"files": [
"index.md",
"toc.yml"
]
},
{
"src": "docs/guide",
"dest": "guide",
"files": [
"**.md",
"**/toc.yml"
]
},
{
"src": "docs/api",
"dest": "api",
"files": [
"**.yml",
"index.md"
]
}
],
"resource": [
{
"src": "docs",
"files": [
"images/**"
]
}
],
"output": "artifacts",
"fileMetadataFiles": [],
"postProcessors": [],
"keepFileLink": false,
"disableGitFeatures": false,
"template": [
"default",
"docs/templates/singulinkfx"
],
"globalMetadata": {
"_appTitle": "GW2SDK",
"_appName": "GW2SDK",
"_appLogoPath": "images/logo-50x50.png",
"_appFaviconPath": "images/logo-50x50.png",
"_appFooter": "Built with docfx, theme created by Singulink",
"_copyrightFooter": "© Steven Liekens. All rights reserved.",
"_enableSearch": true,
"_enableNewTab": true
}
}
}
- Exceptions
Creating output...
ArgumentException: An item with the same key has already been added. Key: System
at bool TryInsert(TKey key, TValue value, InsertionBehavior behavior)
at void Add(TKey key, TValue value)
at MetadataItem GenerateNestedTocStructure(IEnumerable<KeyValuePair<string, MetadataItem>> namespaces, Dictionary<string, ReferenceItem> allReferences) in YamlMetadataResolver.cs:105
at MetadataItem GenerateNestedToc(IEnumerable<KeyValuePair<string, MetadataItem>> namespaces, Dictionary<string, ReferenceItem> allReferences) in YamlMetadataResolver.cs:162
at MetadataItem GenerateToc(Dictionary<string, MetadataItem> allMembers, Dictionary<string, ReferenceItem> allReferences, NamespaceLayout namespaceLayout) in YamlMetadataResolver.cs:56
at MetadataModel ResolveMetadata(Dictionary<string, MetadataItem> allMembers, Dictionary<string, ReferenceItem> allReferences, NamespaceLayout namespaceLayout) in YamlMetadataResolver.cs:33
at void <CreateManagedReference>g__ResolveAndExportYamlMetadata|2(Dictionary<string, MetadataItem> allMembers, Dictionary<string, ReferenceItem> allReferences) in DotnetApiCatalog.ManagedReference.cs:51
at void CreateManagedReference((ValueTuple<IAssemblySymbol, Compilation> symbol) assemblies, ExtractMetadataConfig config, DotnetApiOptions options) in DotnetApiCatalog.ManagedReference.cs:45
at async Task <Exec>g__Build|4_0(ExtractMetadataConfig config, DotnetApiOptions options) in DotnetApiCatalog.cs:123
at async Task Exec(MetadataJsonConfig config, DotnetApiOptions options, string configDirectory, string outputDirectory) in DotnetApiCatalog.cs:75
at void <Execute>b__0() in DefaultCommand.cs:38
at int Run(LogOptions options, Action run) in CommandHelper.cs:44
at int Execute(CommandContext context, Options options) in DefaultCommand.cs:30
at Task<int> Execute(CommandContext context, CommandSettings settings) in CommandOfT.cs:40
at Task<int> Execute(CommandTree leaf, CommandTree tree, CommandContext context, ITypeResolver resolver, IConfiguration configuration) in CommandExecutor.cs:144
at async Task<int> Execute(IConfiguration configuration, IEnumerable<string> args) in CommandExecutor.cs:83
at async Task<int> RunAsync(IEnumerable<string> args) in CommandApp.cs:84
- .NET info
.NET SDK:
Version: 8.0.100
Commit: 57efcf1350
Workload version: 8.0.100-manifests.6c33ef20
Runtime Environment:
OS Name: debian
OS Version: 12
OS Platform: Linux
RID: linux-x64
Base Path: /usr/share/dotnet/sdk/8.0.100/
.NET workloads installed:
Workload version: 8.0.100-manifests.6c33ef20
There are no installed workloads to display.
Host:
Version: 8.0.0
Architecture: x64
Commit: 5535e31a71
.NET SDKs installed:
8.0.100 [/usr/share/dotnet/sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 8.0.0 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 7.0.14 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.0 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
Other architectures found:
None
Environment variables:
DOTNET_ROOT [/usr/share/dotnet]
global.json file:
/workspaces/gw2sdk/global.json
Learn more:
https://aka.ms/dotnet/info
Download .NET:
https://aka.ms/dotnet/download
A few minutes of debugging tells me that the problem occurs because I have a (generated) type in the System
namespace, which causes a conflict in GenerateNestedTocStructure
because allReferences
already contains "System"
, so there is a duplicate key error when trying to add the namespace to namespacedItems
and again to allReferences
.
We have a similar problem, but the namespace-specific:
ArgumentException: An item with the same key has already been added. Key: <...>.HttpClient
at bool TryInsert(TKey key, TValue value, InsertionBehavior behavior)
at void Add(TKey key, TValue value)
at MetadataItem GenerateNestedTocStructure(IEnumerable<KeyValuePair<string, MetadataItem>> namespaces, Dictionary<string, ReferenceItem> allReferences) in YamlMetadataResolver.cs:105
at MetadataItem GenerateNestedToc(IEnumerable<KeyValuePair<string, MetadataItem>> namespaces, Dictionary<string, ReferenceItem> allReferences) in YamlMetadataResolver.cs:162
at MetadataItem GenerateToc(Dictionary<string, MetadataItem> allMembers, Dictionary<string, ReferenceItem> allReferences, NamespaceLayout namespaceLayout) in YamlMetadataResolver.cs:56
at MetadataModel ResolveMetadata(Dictionary<string, MetadataItem> allMembers, Dictionary<string, ReferenceItem> allReferences, NamespaceLayout namespaceLayout) in YamlMetadataResolver.cs:33
at void <CreateManagedReference>g__ResolveAndExportYamlMetadata|2(Dictionary<string, MetadataItem> allMembers, Dictionary<string, ReferenceItem> allReferences) in DotnetApiCatalog.ManagedReference.cs:
51
at void CreateManagedReference((ValueTuple<IAssemblySymbol, Compilation> symbol) assemblies, ExtractMetadataConfig config, DotnetApiOptions options) in DotnetApiCatalog.ManagedReference.cs:45
at async Task <Exec>g__Build|5_0(ExtractMetadataConfig config, DotnetApiOptions options) in DotnetApiCatalog.cs:120
at async Task Exec(MetadataJsonConfig config, DotnetApiOptions options, string configDirectory, string outputDirectory) in DotnetApiCatalog.cs:72
at void <Execute>b__0() in MetadataCommand.cs:18
at int Run(LogOptions options, Action run) in CommandHelper.cs:48
at int Execute(CommandContext context, MetadataCommandOptions options) in MetadataCommand.cs:14
at Task<int> Execute(CommandContext context, CommandSettings settings) in CommandOfT.cs:40
at Task<int> Execute(CommandTree leaf, CommandTree tree, CommandContext context, ITypeResolver resolver, IConfiguration configuration) in CommandExecutor.cs:144
at async Task<int> Execute(IConfiguration configuration, IEnumerable<string> args) in CommandExecutor.cs:83
at async Task<int> RunAsync(IEnumerable<string> args) in CommandApp.cs:84
I replaced the actual namespace with <...>
.
In our case we have a couple of assemblies that offer different extensions for HttpClient
, but share the same namespace.
With "namespaceLayout": "flattened"
we don't have any issues.
A few minutes of debugging tells me that the problem occurs because I have a (generated) type in the
System
namespace, which causes a conflict inGenerateNestedTocStructure
becauseallReferences
already contains"System"
, so there is a duplicate key error when trying to add the namespace tonamespacedItems
and again toallReferences
.
Just chiming in to say that I have pretty much the same issue - an extension method in the System
namespace residing in my own assembly prompts the same error. (Whether I should be doing that or not is a separate question...)
It seems original reported issue can be resolved by updating PolySharp to PolySharp 1.14.1
If there are another issue that relating to namespace
and "namespaceLayout": "nested"
.
Please provide minimal reproduceable project files.