Where the overlap comes from
A oneOf schema accepts a value only when exactly one branch validates. Consider a response that can contain a receipt or an invoice:
{
"oneOf": [
{
"type": "object",
"properties": { "receiptId": { "type": "string" } },
"required": ["receiptId"]
},
{
"type": "object",
"properties": { "invoiceId": { "type": "string" } },
"required": ["invoiceId"]
}
]
}
A response such as {"receiptId":"receipt","invoiceId":"invoice"} looks plausible. It has both identifiers, and each has the expected type. Yet it fails oneOf: the receipt branch accepts it, and the invoice branch accepts it too.
The overlap comes from two object-schema rules. required says a named property must be present. It does not say other properties must be absent. By default, an object may also contain properties that its branch does not describe. Each branch therefore accepts the other branch’s identifier as an extra property.
Neither branch fails on its own. The failure appears when oneOf checks how many branches accept the response. Removing one identifier from this example leaves one matching branch. Keeping both produces two matches. The response does not indicate which branch was intended.
Make each branch identifiable
If the response has distinct kinds, require a kind property in each branch and give it a different const value:
{
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "const": "receipt" },
"receiptId": { "type": "string" }
},
"required": ["kind", "receiptId"]
},
{
"type": "object",
"properties": {
"kind": { "const": "invoice" },
"invoiceId": { "type": "string" }
},
"required": ["kind", "invoiceId"]
}
]
}
const requires one fixed value. With kind required, a response cannot satisfy both branches through that property. A response still needs the identifier required by its chosen branch.
A response with both identifiers can still pass this revised schema if its kind selects one branch. Extra properties remain allowed. If the response must exclude the unused identifier, add an explicit property constraint to each branch. If a response is meant to satisfy either branch even when both match, anyOf allows one or more matches.
What to do
Check each proposed response against every branch, especially responses containing fields from several branches. For oneOf, make the branches mutually exclusive with required fixed values or other explicit constraints. Add examples that should match one branch, both branches, and neither branch, then validate each against the complete schema.

The Campfire
No commentsNobody has pulled up a log by this one yet. Be the first to say what you make of it.
Held for the desk. It appears after a look.