Skip to main content

Troubleshooting & FAQ

Common Issues​

AddDefaultsDocumentTransformer throws ArgumentNullException​

Cause: OpenApiOptions is null when calling the extension method.

Fix: Ensure AddOpenApi() is called before chaining:

// ❌
OpenApiOptions? opts = null;
opts.AddDefaultsDocumentTransformer(); // throws

// ✅
builder.Services.AddOpenApi(options =>
{
options.AddDefaultsDocumentTransformer();
});

DependencyInjectionExtensions not found after upgrading to v10.1.1​

Cause: In v10.1.1 the class was renamed from DependencyInjectionExtensions to OpenApiOptionsExtensions (and its methods are now C# 14 extension members).

Fix: Replace class-name references — typeof(DependencyInjectionExtensions), static calls, reflection strings — with OpenApiOptionsExtensions. Regular extension-method call sites like options.AddDefaultsDocumentTransformer() are unaffected.

RA.Utilities.Api.Results no longer compiles in my custom transformer​

Cause: This package now references RA.Utilities.Api.Response 10.1.0, which moved its models from the RA.Utilities.Api.Results namespace to RA.Utilities.Api.Response.

Fix: Update the using directive in your custom transformers or examples:

// Before
using RA.Utilities.Api.Results;

// After
using RA.Utilities.Api.Response;

OpenApiOperationUtilities.AddGeneralErrorResponse and the DefaultResponsesOperationTransformer schema also use ErrorResponse from this package; the OpenApi public API itself is unchanged.

AddHealthChecksDocumentTransformer(tags) doesn't add the health check endpoints​

Cause: Known bug in v10.1.0 through v10.3.0 — the method registers HeadersParameterTransformer instead of HealthChecksDocumentTransformer, and ignores tags.

Fix: Register the default pipeline instead:

builder.Services.AddOpenApi(options =>
{
options.AddDefaultsDocumentTransformer();
});

AddDefaultsDocumentTransformer() registers HealthChecksDocumentTransformer after the Bearer security transformer, so /health and /alive stay anonymous.

Group summary or description doesn't appear on the tag​

Cause: One of the following:

  • GroupTagsDocumentTransformer isn't registered. AddDefaultsDocumentTransformer() registers it automatically; if you register transformers individually, call options.AddGroupTagsDocumentTransformer(...).
  • The route group and its endpoints carry no tags. Group text is written only to the tags returned by WithTags(...).
  • The tag already has a non-empty description. Group text only fills empty descriptions — an explicit AddTagOperationTransformer() description always wins.

Fix: Register the transformer and tag the group:

builder.Services.AddOpenApi(options =>
{
options.AddDefaultsDocumentTransformer(); // includes GroupTagsDocumentTransformer
});

var orders = app.MapGroup("/orders")
.WithTags("Orders")
.WithGroupSummary("Order management")
.WithGroupDescription("Create, update, and track customer orders.");

AddResponseExamples ignores my MediaType​

Cause: AddResponseExamples forwards each item to AddResponseExample without the per-item MediaType, so batched response examples always use application/json.

Fix: Add the examples individually when you need another media type:

OpenApiOperationUtilities.AddResponseExample(
operation,
StatusCodes.Status400BadRequest,
"ValidationError",
example,
mediaType: "application/problem+json");

Swagger UI doesn't show the Authorize button​

Cause: BearerSecurityDocumentTransformer wasn't registered, or JWT Bearer authentication isn't configured.

Fix: Register the transformer and ensure authentication is set up:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(/* ... */);

builder.Services.AddOpenApi(options =>
options.AddBearerSecurityDocumentTransformer());

The transformer checks for registered authentication schemes named "Bearer" or "BearerToken".

Header parameters aren't appearing in the OpenAPI doc​

Cause: HeadersParameterSettings aren't bound from configuration, or HeadersParameterTransformer isn't registered.

Fix: Bind the settings and register the transformer:

builder.Services.Configure<HeadersParameterSettings>(
builder.Configuration.GetSection(HeadersParameterSettings.AppSettingsKey));

builder.Services.AddOpenApi(options =>
options.AddHeadersParameterTransformer());

FluentValidation rules aren't reflected in the schema​

Cause: The validators aren't registered in DI, or AddFluentValidationRules() wasn't called.

Fix: Register validators and the transformer:

// Register validators
builder.Services.AddValidatorsFromAssembly(typeof(Program).Assembly);

// Register schema transformer
builder.Services.AddOpenApi(options =>
options.AddFluentValidationRules());

The transformer resolves IValidator<T> from DI for each schema type. If the validator isn't registered, the schema is left unchanged.

Value objects have no type, pattern, or length in the schema​

Cause: ValueObjectSchemaTransformer isn't registered. The OpenAPI generator cannot see the validation performed by the value object constructors, so it emits Email, Currency, SSN, and IBAN as property-less objects.

Fix: Register the default pipeline or the transformer explicitly:

builder.Services.AddOpenApi(options =>
options.AddValueObjectSchemaTransformer());

AddDefaultsDocumentTransformer() already registers it. Once registered, Email, Currency, SSN, and IBAN become string schemas with format, pattern, minLength, and maxLength, and Money gets a description and example. The transformer also covers route, query, and header parameters.

Enum descriptions aren't appearing​

Cause: Either the XML documentation file path is wrong, or the file doesn't exist, or the enum members don't have XML comments.

Fix: Verify the XML file is generated and the path is correct:

var xmlPath = Path.Combine(AppContext.BaseDirectory, "MyApi.xml");

if (!File.Exists(xmlPath))
{
throw new FileNotFoundException($"XML doc file not found: {xmlPath}");
}

builder.Services.AddOpenApi(options =>
options.AddEnumXmlDescriptionTransformer(xmlPath));

Also ensure your enum members have <summary> XML comments.

Polymorphism discriminator isn't working​

Cause: The base schema name doesn't match the type passed to AddPolymorphismDocumentTransformer<T>().

Fix: Pass the correct base type as the generic parameter:

// ✅ The base type T must match the schema you want to transform
options.AddPolymorphismDocumentTransformer<Animal>(new Dictionary<string, Type>
{
{ "Cat", typeof(Cat) },
{ "Dog", typeof(Dog) },
});

FAQ​

What's the difference between a Document Transformer and an Operation Transformer?​

Document TransformerOperation Transformer
InterfaceIOpenApiDocumentTransformerIOpenApiOperationTransformer
ScopeEntire OpenAPI documentIndividual API operation
Use forInfo, security schemes, global headersPer-operation responses, parameters

Do I need AddOpenApi() before using these transformers?​

Yes — the extension methods extend OpenApiOptions, so they must be called from the AddOpenApi(Action<OpenApiOptions>) overload:

builder.Services.AddOpenApi(options =>
{
options.AddDefaultsDocumentTransformer();
options.AddFluentValidationRules();
});

Note that AddOpenApi() itself returns IServiceCollection, so AddOpenApi().AddDefaultsDocumentTransformer() does not compile.

Can I use multiple schema transformers together?​

Yes. Register them all:

builder.Services.AddOpenApi(options =>
{
options.AddFluentValidationRules();
options.AddEnumXmlDescriptionTransformer(xmlPath);
});

Why are the transformers internal?​

Transformers are internal sealed to enforce registration through the provided extension methods. This ensures consistent configuration, proper dependency injection, and the ability to change internal implementations without breaking consumers.

Does AddDefaultsDocumentTransformer() include everything?​

No. It registers five document transformers — DocumentInfoTransformer, BearerSecurityDocumentTransformer, HeadersParameterTransformer, HealthChecksDocumentTransformer, and GroupTagsDocumentTransformer — plus the ValueObjectSchemaTransformer. The operation transformer (DefaultResponsesOperationTransformer) and the remaining schema transformers must be registered separately.

How do I exclude specific endpoints from a transformer?​

Document transformers apply globally. To exclude specific endpoints, use a custom operation transformer that checks the operation's metadata, or write a custom document transformer that filters document.Paths before delegating. Configuration settings such as HeadersParameterSettings are global; they do not support per-endpoint overrides.


Known Limitations​

  • AddHealthChecksDocumentTransformer(tags) is broken in v10.1.0 through v10.3.0: it registers HeadersParameterTransformer and ignores tags. Use AddDefaultsDocumentTransformer().
  • AddGroupTagsDocumentTransformer(tags) ignores tags: the argument is required by the current signature but unused; group text comes from WithGroupSummary() / WithGroupDescription(). Use AddDefaultsDocumentTransformer(), which registers the transformer automatically.
  • Group documentation requires tags: WithGroupSummary() / WithGroupDescription() write to the tags the group's endpoints carry; without .WithTags(...) there is no tag to describe. Existing tag descriptions are never overwritten.
  • AddResponseExamples ignores per-item MediaType: batched response examples always use application/json; use AddResponseExample for custom media types.
  • No endpoint exclusion: Document transformers apply to all operations. Use custom transformers for per-endpoint behavior.
  • Single XML file: EnumXmlSchemaTransformer currently supports only one XML documentation file.
  • FluentValidation scope: Only validators registered in the DI container are discovered. Attributes-based validation (DataAnnotations) is not supported.
  • Numeric responseType in default examples: DefaultResponsesOperationTransformer serializes new ErrorResponse() with default System.Text.Json options, so the example's responseType is numeric. Register JsonStringEnumConverter for string values.