Swashbuckle.aspnetcore: 5.0.0-rc5, Can't use schemaId "$Nullable`1" for type...

Created on 24 Dec 2019  路  10Comments  路  Source: domaindrivendev/Swashbuckle.AspNetCore

Hi Guys,

Today we tried to upgrade from rc4 to rc5 and failed. On the attempt to open swagger ui page we get following exception:

System.InvalidOperationException: Can't use schemaId "$Nullable`1" for type "$System.Nullable`1[EDW.CrewPage.Model.Enums.Database.ShadowDutyType]". The same schemaId is already used for type "$System.Nullable`1[EDW.CrewPage.Model.Enums.CommentCategory]"
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaRepository.ReserveIdFor(Type type, String schemaId)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaRepository.GetOrAdd(Type type, String schemaId, Func`1 factoryMethod)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGeneratorBase.CreateReferenceSchema(Type type, SchemaRepository schemaRepository, Func`1 factoryMethod)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGeneratorBase.GenerateSchema(Type type, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.JsonObjectHandler.GeneratePropertySchema(PropertyInfo property, IEnumerable`1 customAttributes, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.JsonObjectHandler.CreateDefinitionSchema(Type type, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGeneratorBase.<>c__DisplayClass4_1.<GenerateSchema>b__0()
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaRepository.GetOrAdd(Type type, String schemaId, Func`1 factoryMethod)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGeneratorBase.CreateReferenceSchema(Type type, SchemaRepository schemaRepository, Func`1 factoryMethod)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGeneratorBase.GenerateSchema(Type type, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.JsonArrayHandler.CreateDefinitionSchema(Type type, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SchemaGeneratorBase.GenerateSchema(Type type, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.CreateResponseMediaType(ModelMetadata modelMetadata, SchemaRepository schemaRespository)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.<>c__DisplayClass18_0.<GenerateResponse>b__2(String contentType)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateResponse(ApiDescription apiDescription, SchemaRepository schemaRepository, String statusCode, ApiResponseType apiResponseType)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateResponses(ApiDescription apiDescription, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperation(ApiDescription apiDescription, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperations(IEnumerable`1 apiDescriptions, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GeneratePaths(IEnumerable`1 apiDescriptions, SchemaRepository schemaRepository)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GetSwagger(String documentName, String host, String basePath)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at FirstQuad.DatabaseUpdater.Core.DatabaseUpdaterMiddleware.Invoke(HttpContext httpContext)
   at EDW.CrewPage.WebApi.Code.Middleware.MaintenanceCheckMiddleware.Invoke(HttpContext context) in C:\Dev\1stquad\edw.crewpage\Source\EDW.CrewPage.WebApi\Code\Middleware\MaintenanceCheckMiddleware.cs:line 46
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

So, we returned to the rc4 and things work just fine.
Any idea what's wrong and how this could be fixed?

Thanks, regards

Most helpful comment

Maybe you should to use FullName of you scheme type?
Try this one

 services.AddSwaggerGen(options =>
 {
       options.CustomSchemaIds(type => type.FullName);
 });

or

 services.AddSwaggerGen(options =>
 {
       options.CustomSchemaIds(type => type.ToString());
 });

All 10 comments

Also experiencing this issue, solved the same way.

@yahorsi schemaIds are used to reference the definition for a given type and therefore MUST be unique to that type. However, according to the message above, an ID value of "$Nullable`1" is being presented for two different types.

The default schemaId generation strategy _should_ ensure the per-type uniqueness out-of-the-box. So, I'm wondering if you're providing a custom strategy (i.e. via the CustomSchemaIds config setting)? If so, it seems your custom strategy may be flawed because it is NOT returning unique IDs.

Stumbled upon the same problem.
Works with the latest preview version (https://www.myget.org/feed/domaindrivendev/package/nuget/Swashbuckle.AspNetCore).

If so, it seems your custom strategy may be flawed because it is NOT returning unique IDs.

That might be the case. Here is the custom strategy:

                    c.CustomOperationIds(apiDesc =>
                    {
                        var methodName = apiDesc.TryGetMethodInfo(out MethodInfo methodInfo) ? methodInfo.Name : null;

                        return methodName;
                    });

The reason for that strategy is to omit namespaces in the generated spec. We had it in 2.2 and in rc4 and it was working just fine. The problem is that now, it does not work as causing an exception.

PS: Sorry for delays in answer, EOY rush and holidays afterwards

The code you showed me above is for operationId as opposed to schemaId. Does you're configuration use CustomSchemaIds anywhere?

The reason for that strategy is to omit namespaces in the generated spec. We had it in 2.2 and in rc4 and it was working just fine. The problem is that now, it does not work as causing an exception.

Also worth noting that the default strategy already omits namespaces so if this is the reason for the custom strategy then you may not need it

The reason for that strategy is to omit namespaces in the generated spec. We had it in 2.2 and in rc4 and it was working just fine. The problem is that now, it does not work as causing an exception.

Also worth noting that the default strategy already omits namespaces so if this is the reason for the custom strategy then you may not need it

Thank you for letting me know! Will try it and report here on monday

Maybe you should to use FullName of you scheme type?
Try this one

 services.AddSwaggerGen(options =>
 {
       options.CustomSchemaIds(type => type.FullName);
 });

or

 services.AddSwaggerGen(options =>
 {
       options.CustomSchemaIds(type => type.ToString());
 });

I hit this too (5.0.0 final release) and have no custom schemaId generation. I do however have TWO enum classes with the same name (both are called "Status", inside a class called "Enum", but are in different namespaces). The suggestion above fixed it.

Closing for now, as providing a custom schema Id strategy is the recommended appraoch to workaround conflicting type names.

Was this page helpful?
0 / 5 - 0 ratings