RicoSuter/NSwag · error · InvalidOperationException

Some operations are both in included and excluded operation…

Error message

Some operations are both in included and excluded operation IDs ({operationsBothIncludedAndExcluded}).

What it means

When generating a client, NSwag filters operations by IncludedOperationIds and ExcludedOperationIds (usually via x-operation-id and SwaggerOperation attributes). GetOperations throws InvalidOperationException if any operation ID appears in both sets, since inclusion and exclusion are mutually exclusive filters.

Solutions

  1. Remove the conflicting operation IDs from ExcludedOperationIds (or IncludedOperationIds) so the sets do not intersect.
  2. Compute ExcludedOperationIds as allIds.Except(IncludedOperationIds) when deriving one list from the other.
  3. Verify operation IDs in attributes (SwaggerOperation) match exactly one list, not both.

Example fix

// before
settings.IncludedOperationIds = new[] { "GetUser", "CreateUser" };
settings.ExcludedOperationIds = new[] { "CreateUser" };
// after
settings.IncludedOperationIds = new[] { "GetUser", "CreateUser" };
settings.ExcludedOperationIds = new[] { "DeleteUser" };
Defensive patterns

Strategy: validation

Validate before calling

var overlap = settings.IncludedOperationIds?.Intersect(settings.ExcludedOperationIds ?? Enumerable.Empty<string>()).ToList();
if (overlap?.Any() == true) throw new ArgumentException($"Operation IDs both included and excluded: {string.Join(\",\", overlap)}");

Type guard

bool NoIncludeExcludeOverlap(ISystem.Collections.Generic.IEnumerable<string> inc, IEnumerable<string> exc) => !(inc ?? []).Intersect(exc ?? []).Any();

Try / catch

try { var code = generator.Generate(file); }
catch (InvalidOperationException ex) when (ex.Message.Contains("included and excluded operation IDs")) { logger.LogError(ex, "Fix IncludedOperationIds/ExcludedOperationIds overlap"); throw; }

Prevention

When it happens

Trigger: Setting config.IncludedOperationIds = ["Op1"] and config.ExcludedOperationIds = ["Op1"] (overlapping sets) on generator/client settings before calling GenerateAsync or nswag codegen.

Common situations: Building include/exclude lists programmatically from overlapping selectors (e.g. excluding by tag while including by ID); config files where one operation was added to both lists over time.

Related errors


AI-assisted analysis of RicoSuter/NSwag@63daf8fcc3 (2026-09-14). Data as JSON: /api/errors/90fb1c93dc7e7be4. Report an issue: GitHub.

Appendix: source

Thrown at src/NSwag.CodeGeneration/ClientGeneratorBase.cs:166

        /// <param name="operation">The operation.</param>
        /// <param name="settings">The settings.</param>
        /// <returns>The operation model.</returns>
        protected abstract TOperationModel CreateOperationModel(OpenApiOperation operation,
            ClientGeneratorBaseSettings settings);

        private static readonly char[] pathTrimChars = ['/'];

        private List<TOperationModel> GetOperations(OpenApiDocument document)
        {
            document.GenerateOperationIds();

            HashSet<string> operationsToInclude = [..BaseSettings.IncludedOperationIds ?? []];
            HashSet<string> operationsToExclude = [.. BaseSettings.ExcludedOperationIds ?? []];

            IEnumerable<string> operationsBothIncludedAndExcluded = operationsToInclude.Intersect(operationsToExclude);
            if (operationsBothIncludedAndExcluded.Any())
            {
                throw new InvalidOperationException(
                    $"Some operations are both in included and excluded operation IDs ({string.Join(", ", operationsBothIncludedAndExcluded)})."
                    );
            }

            var result = new List<TOperationModel>();
            foreach (var pair in document.Paths)
            {
                foreach (var p in pair.Value.ActualPathItem)
                {
                    var operation = p.Value;
 
                    if ((operationsToInclude.Count is not 0 && !operationsToInclude.Contains(operation.OperationId))
                        ||
                        (operationsToExclude.Count is not 0 && operationsToExclude.Contains(operation.OperationId))
                        )
                    {
                        continue;
                    }

View on GitHub (pinned to 63daf8fcc3)