Minimal reproduction
With SwaggerProvider 4.0.0 or 4.1.0 and .NET SDK 10.0.301:
open SwaggerProvider
type ReproApi =
OpenApiClientProvider<"repro.json", SsrfProtection=false>
let client = ReproApi.Client()
{
"openapi": "3.0.0",
"info": { "title": "Named object alias reproduction", "version": "1.0.0" },
"paths": {
"/parent": {
"get": {
"operationId": "getParent",
"responses": {
"200": {
"description": "Parent response",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/Parent" }
}
}
}
}
}
}
},
"components": {
"schemas": {
"Parent": {
"oneOf": [
{ "$ref": "#/components/schemas/Parent_Child" }
]
},
"Parent_Child": {
"type": "object",
"required": ["childValue"],
"properties": {
"childValue": { "type": "string" }
}
}
}
}
}
The equivalent single-reference anyOf and allOf component aliases fail in the same way.
Version matrix
| SwaggerProvider |
Result |
| 4.0.0 |
Reproduced |
| 4.1.0 |
Reproduced |
Actual behavior
dotnet build fails while emitting the provided assembly:
FS3033: The type provider 'SwaggerProvider.OpenApiClientTypeProvider' reported an error: duplicate entry 'Parent_Child' in type index table
Expected behavior
Parent resolves to the generated Parent_Child object type.
- The
Parent component path is cached as an alias to that type.
Parent_Child is added to the generated namespace exactly once.
- An operation returning
Parent exposes the properties generated for Parent_Child.
Root-cause analysis
DefinitionCompiler.compileSingleRefOrNewObject recognizes that Parent is a single-reference alias, releases the Parent name reservation, and resolves Parent_Child.
At the end of compileBySchema, the unconditional registerNew(tyName, tyType) call for fromByPathCompiler both caches the component path and registers the returned type in the namespace. The returned ProvidedTypeDefinition is the already-generated Parent_Child, so it is registered under both component entries. NamespaceAbstraction.GetProvidedTypes() consequently returns the same provided type more than once, and assembly emission fails with the duplicate type-index entry.
The fix should separate component-path caching from namespace registration for aliases, rather than suppressing, renaming, dropping, or weakening the generated type.
PR #375 did not cover this case. Its regression tests place a single-reference wrapper on an object property that points to a primitive alias. They do not compile a named top-level component that aliases another named object component, so no duplicate ProvidedTypeDefinition is emitted.
Minimal reproduction
With
SwaggerProvider4.0.0 or 4.1.0 and .NET SDK 10.0.301:{ "openapi": "3.0.0", "info": { "title": "Named object alias reproduction", "version": "1.0.0" }, "paths": { "/parent": { "get": { "operationId": "getParent", "responses": { "200": { "description": "Parent response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Parent" } } } } } } } }, "components": { "schemas": { "Parent": { "oneOf": [ { "$ref": "#/components/schemas/Parent_Child" } ] }, "Parent_Child": { "type": "object", "required": ["childValue"], "properties": { "childValue": { "type": "string" } } } } } }The equivalent single-reference
anyOfandallOfcomponent aliases fail in the same way.Version matrix
Actual behavior
dotnet buildfails while emitting the provided assembly:Expected behavior
Parentresolves to the generatedParent_Childobject type.Parentcomponent path is cached as an alias to that type.Parent_Childis added to the generated namespace exactly once.Parentexposes the properties generated forParent_Child.Root-cause analysis
DefinitionCompiler.compileSingleRefOrNewObjectrecognizes thatParentis a single-reference alias, releases theParentname reservation, and resolvesParent_Child.At the end of
compileBySchema, the unconditionalregisterNew(tyName, tyType)call forfromByPathCompilerboth caches the component path and registers the returned type in the namespace. The returnedProvidedTypeDefinitionis the already-generatedParent_Child, so it is registered under both component entries.NamespaceAbstraction.GetProvidedTypes()consequently returns the same provided type more than once, and assembly emission fails with the duplicate type-index entry.The fix should separate component-path caching from namespace registration for aliases, rather than suppressing, renaming, dropping, or weakening the generated type.
PR #375 did not cover this case. Its regression tests place a single-reference wrapper on an object property that points to a primitive alias. They do not compile a named top-level component that aliases another named object component, so no duplicate
ProvidedTypeDefinitionis emitted.