← OpenAPI Breaking Change Check

Why does adding an enum count as a breaking change?

A parameter that used to take any string now only accepts three of them, and the checker calls that breaking — even though all you did was add a list of values. That reading is correct, and the same one rule explains it, and every other verdict this tool gives.

An "addition" that narrows is still a narrowing

Before the enum existed, the parameter accepted any value of its declared type: any string, any integer. Restricting it to ["standard", "express", "overnight"] does not add to what the API accepts — it shrinks it. Every value outside that list, including ones a real client could have been sending and getting a valid response for, is now rejected. The list itself is new; what changed for an existing client is that the API got pickier. That is what openapi_diff.py and this page are classifying as enum-added, and it is reported breaking for the same reason a newly-required parameter is: something that used to work can now fail.

This is a shallow, structural read of the parameter's own schema, not a request-by-request replay against real traffic — see how this compares to reading the spec diff by hand for what that trade gives up.

The one rule behind every verdict

Every change this checker reports, breaking or not, answers the same question: does this shrink what the API accepts from a client that has not changed, or take away something a client could already rely on? A "yes" is breaking. Everything that only adds an option, widens what is accepted, or lifts a restriction is non-breaking — even when the diff itself reads as an addition.

ChangeVerdictWhy
Enum added to a previously unrestricted parameterBreakingNarrows what the parameter accepts
Value added to an existing enumNon-breakingEvery previously-valid value still works
Value removed from an existing enumBreakingA value a client could send is now rejected
Enum constraint removed entirelyNon-breakingEverything that worked before still works, plus more
New required parameterBreakingA request that omitted it used to succeed
New optional parameterNon-breakingOmitting it still works exactly as before

Read this way, the checker has no special case for enums at all — it is the same narrowing-vs-widening test applied to a parameter's value set instead of its required flag or type.

Common questions

Why is restricting a parameter to an enum breaking, when I only added a list of values?

Because before the enum existed, the parameter accepted any value of its declared type — any string, any integer. Restricting it to a fixed list narrows that acceptance: every value outside the new list is a value an existing client could have been sending, and validly, that the API now rejects. The list is new, but what the API accepts got smaller, which is what the checker is classifying.

So is adding a value to an existing enum also breaking?

No, and this is the case most people expect: adding a value to a parameter that already had an enum is reported non-breaking. A client sending one of the old values keeps working exactly as before — the set of accepted values only grew. The breaking case is the opposite direction: a value that used to be accepted disappearing from the list, or the list appearing where there was none before.

What is the one rule behind every verdict this checker gives?

Does this change shrink what the API will accept from a client that has not changed, or take away something a client could already rely on? If yes, it is breaking. If the change only adds an option, widens what is accepted, or removes a restriction, it is non-breaking. A new optional parameter, a new endpoint, and an enum constraint lifted entirely are all widening moves, so all three come back non-breaking even though two of them are literally additions to the spec.

Does removing the enum constraint entirely count as breaking?

No — that direction is reported non-breaking. A parameter that used to accept only a fixed list and now accepts any value of its type still accepts everything an existing client was already sending, plus more. Nothing that worked before stops working, which is why the checker treats lifting a restriction as widening rather than narrowing.

Want the tool itself, or how it compares to oasdiff's much deeper change catalogue? See OpenAPI Breaking Change Check, or how this compares to oasdiff.