Skip to content

fix: treat a required request body becoming optional as compatible - #940

Open
Inf1mum wants to merge 1 commit into
OpenAPITools:masterfrom
Inf1mum:fix/329-request-body-optional
Open

Inf1mum wants to merge 1 commit into
OpenAPITools:masterfrom
Inf1mum:fix/329-request-body-optional

Conversation

@Inf1mum

@Inf1mum Inf1mum commented Nov 15, 2026 •

Copy link
Copy Markdown

Fixes #329

What

Diffing a spec where an operation's request body changed from required: true to optional (required: false or the key removed) now reports a compatible change instead of an incompatible one. The reverse direction, optional to required, stays incompatible.

Why

Making a required request body optional cannot break existing clients: they keep sending the body, and the server must keep accepting it under the new spec. Reporting that as breaking is a false positive that blocks CI pipelines relying on --fail-on-incompatible.

How

ChangedRequestBody.isCoreChanged() now short-circuits to COMPATIBLE when both the old and new request bodies exist and only the required flag decreases, mirroring the directional checks already used by ChangedRequired (schema properties) and ChangedReadOnly:

  • required -> optional: compatible, still listed under "What's Changed" as a non-breaking change
  • optional -> required: incompatible, now gated by the previously unused incompatible.request.body.increased property (REQUEST_BODY_REQUIRED_INCREASED) instead of incompatible.openapi.endpoints.decreased, which the request body check had been borrowing as a placeholder. Wiring the intended property also brings the request body in line with every other backward-incompatibility check, which gates on its own property.
  • a removed request body whose old body was required: still incompatible (both bodies must exist for the compatible short-circuit to apply)

Tests

  • RequestBodyBCTest now covers both directions: requiredIncreased (incompatible when incompatible.request.body.increased is enabled, compatible when disabled) and requiredDecreasedButCompatible (always compatible)
  • RequestDiffTest gains model-level assertions for both directions, checking the operation and spec-level verdicts
  • Full ./mvnw test is green

CLI check

For required: true -> required: false on the same operation:

$ openapi-diff old.yaml new.yaml --state
compatible

and the reverse pair still reports incompatible.


Summary by cubic

Fixes #329: a request body changing from required: true to optional (required: false or the key removed) is now reported as a compatible change instead of an incompatible one. Optional to required stays incompatible.

  • Making a required body optional cannot break existing clients that keep sending the body, so the change shows under "What's Changed" as non-breaking.
  • The optional-to-required check now gates on the intended incompatible.request.body.increased property instead of borrowing incompatible.openapi.endpoints.decreased.
  • A removed request body whose old body was required stays incompatible.

Written for commit 58c1d97. Summary will update on new commits.

View guided diff

What:
- a request body changing from required to optional is now reported
  as a compatible change instead of an incompatible one
- optional -> required stays incompatible; the check is now gated by
  the previously unused incompatible.request.body.increased property
  (REQUEST_BODY_REQUIRED_INCREASED) instead of
  incompatible.openapi.endpoints.decreased
- a removed request body whose old body was required stays
  incompatible

Why:
- existing clients that keep sending the body still work when the
  body becomes optional, so the change cannot break them (Fixes OpenAPITools#329)

How:
- ChangedRequestBody.isCoreChanged short-circuits to COMPATIBLE when
  both bodies exist and only the required flag decreases, mirroring
  the directional checks in ChangedRequired and ChangedReadOnly
- RequestBodyBCTest now covers both directions and RequestDiffTest
  gains model-level assertions for both directions

Signed-off-by: Inf1mum <vadimlazuk5@gmail.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. 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. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="core/src/test/java/org/openapitools/openapidiff/core/RequestDiffTest.java">

<violation number="1" location="core/src/test/java/org/openapitools/openapidiff/core/RequestDiffTest.java:38">
P2: The new tests do not cover the stated invariant that removing a required request body remains incompatible. Add an old-required/new-no-`requestBody` fixture and assert the resulting operation and spec are incompatible.</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic

}

@Test
public void testRequestBodyRequiredIncreasedIsIncompatible() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The new tests do not cover the stated invariant that removing a required request body remains incompatible. Add an old-required/new-no-requestBody fixture and assert the resulting operation and spec are incompatible.

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 core/src/test/java/org/openapitools/openapidiff/core/RequestDiffTest.java, line 38:

<comment>The new tests do not cover the stated invariant that removing a required request body remains incompatible. Add an old-required/new-no-`requestBody` fixture and assert the resulting operation and spec are incompatible.</comment>

<file context>
@@ -12,4 +15,37 @@ public class RequestDiffTest {
+  }
+
+  @Test
+  public void testRequestBodyRequiredIncreasedIsIncompatible() {
+    // optional -> required: clients that do not send the body break
+    ChangedOpenApi changedOpenApi =
</file context>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

False positive breaking change when making a required request body optional

1 participant