Skip to content

[BUG][csharp][restsharp] throwOnAnyError: oneOf/anyOf deserialization failure on 2xx escapes as InvalidDataException instead of ApiException #25218

Open

Description

@mszopa-foss
Description

With throwOnAnyError=true the generated ApiClient promises that every failure surfaces as ApiException. For a 2xx response whose body matches none of the oneOf/anyOf variants, FromJson throws InvalidDataException after the ErrorException guard has already passed, so the raw exception reaches the caller without status code, body or headers.

openapi-generator version

master (after #25217)

Steps to reproduce
  1. Generate a csharp client with --library restsharp --additional-properties throwOnAnyError=true from a spec where an operation returns a oneOf model.
  2. Call that operation against a server that returns 200 with a body matching no variant.
  3. Observe InvalidDataException instead of ApiException.
Expected behaviour

ApiException with ErrorCode = 200, ErrorContent = raw body, Headers populated, and the InvalidDataException as InnerException.

Original findings

P2: The FromJson call below can throw InvalidDataException for a 2xx body that matches no oneOf/anyOf schema, after this check has passed; the raw exception escapes instead of the promised ApiException. Wrap that parse failure with the response status, content, and headers.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At modules/openapi-generator/src/main/resources/csharp/ApiClient.mustache, line 500:

<comment>The `FromJson` call below can throw `InvalidDataException` for a 2xx body that matches no oneOf/anyOf schema, after this check has passed; the raw exception escapes instead of the promised `ApiException`. Wrap that parse failure with the response status, content, and headers.</comment>

<file context>
@@ -495,6 +494,14 @@ namespace {{packageName}}.Client
+                {{#throwOnAnyError}}
+
+                // 4xx/5xx also carry ErrorException; those go through ExceptionFactory so the body is kept
+                if (response.ErrorException != null && (int)response.StatusCode < 400)
+                {
+                    throw new ApiException((int)response.StatusCode, string.Format("Error calling {0}: {1}", request.Resource, response.ErrorMessage), response.Content, ToApiResponse(response).Headers);
</file context>

Originally posted by @cubic-dev-ai[bot] in #25217

Activity

  1. changed the title [-][BUG] Description[/-] [+][BUG][csharp][restsharp] throwOnAnyError: oneOf/anyOf deserialization failure on 2xx escapes as InvalidDataException instead of ApiException[/+] on Oct 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions