Describe the bug
ucp.json declares no oneOf in the spec — its root carries only $id, $schema, title, description and $defs. normalize_metadata_schemas synthesizes one, selecting members by name:
ucp["oneOf"] = [
{"$ref": f"#/$defs/{name}"} for name in metadata_union_members(ucp)
]
return [
name for name in defs
if name in ("platform_schema", "business_schema")
or (name.startswith("response_") and name.endswith("_schema"))
]
Three of the six selected members — response_cart_schema, response_catalog_schema and response_order_schema — have identical bodies, differing only in title and description, which do not affect validation.
oneOf means exactly one. Any instance matching one of those three matches all three, so no input can satisfy the union. Since ucp is a required property on cart, checkout and order, no instance of those three types can validate.
To Reproduce
Verified against ucp 5a5d9e1 and python-sdk a0d8308. Setup as in #72, then:
ucp = json.load(open(root + "/ucp.json"))
v = Draft202012Validator(ucp, registry=reg)
print([e.message for e in v.iter_errors({"version": "2026-04-08"})])
{'version': '2026-04-08'} is valid under each of
{'$ref': '#/$defs/response_cart_schema'},
{'$ref': '#/$defs/response_catalog_schema'},
{'$ref': '#/$defs/response_order_schema'}
Every input fails the same way, including instances carrying capabilities, services or payment_handlers.
Expected behavior
The docstring gives the goal as "a unified ucp metadata property across the entire SDK" — a type union for code generation rather than an exclusivity constraint. anyOf expresses that without asserting distinguishability that nothing verifies:
If oneOf is intended, the members need to be distinguishable — either by deduplicating the three response profiles or by giving each a discriminating property. That would be a spec change; switching to anyOf is not.
Additional context
This predates the current membership rule. Before a763549 the list was hardcoded and already contained both response_cart_schema and response_order_schema — two identical members is already enough to make oneOf unsatisfiable. That commit fixed a real omission (catalog responses were being dropped from every model's ucp field) and, as a side effect, took the duplicate count from two to three.
Why it may not have surfaced. ucp.json is among the documents affected by #72, so eagerly-compiling validators reject it before ever reaching the union. Downstream, pydantic's Union resolves to the first matching member rather than enforcing oneOf, so the generated Python models behave sensibly regardless. It was found while building a Go SDK from the same preprocessed schemas, where enforcing oneOf strictly made Cart, Checkout and Order permanently invalid.
Related but distinct: ucp#615 also concerns oneOf member shapes, in the opposite direction — fulfillment_destination's members compose postal_address inconsistently, forcing consumers to branch. This issue is about members that are indistinguishable. Both bear on whether a oneOf's alternatives are meaningfully different; neither fix addresses the other.
Describe the bug
ucp.jsondeclares nooneOfin the spec — its root carries only$id,$schema,title,descriptionand$defs.normalize_metadata_schemassynthesizes one, selecting members by name:Three of the six selected members —
response_cart_schema,response_catalog_schemaandresponse_order_schema— have identical bodies, differing only intitleanddescription, which do not affect validation.oneOfmeans exactly one. Any instance matching one of those three matches all three, so no input can satisfy the union. Sinceucpis a required property oncart,checkoutandorder, no instance of those three types can validate.To Reproduce
Verified against ucp
5a5d9e1and python-sdka0d8308. Setup as in #72, then:Every input fails the same way, including instances carrying
capabilities,servicesorpayment_handlers.Expected behavior
The docstring gives the goal as "a unified
ucpmetadata property across the entire SDK" — a type union for code generation rather than an exclusivity constraint.anyOfexpresses that without asserting distinguishability that nothing verifies:If
oneOfis intended, the members need to be distinguishable — either by deduplicating the three response profiles or by giving each a discriminating property. That would be a spec change; switching toanyOfis not.Additional context
This predates the current membership rule. Before
a763549the list was hardcoded and already contained bothresponse_cart_schemaandresponse_order_schema— two identical members is already enough to makeoneOfunsatisfiable. That commit fixed a real omission (catalog responses were being dropped from every model'sucpfield) and, as a side effect, took the duplicate count from two to three.Why it may not have surfaced.
ucp.jsonis among the documents affected by #72, so eagerly-compiling validators reject it before ever reaching the union. Downstream, pydantic'sUnionresolves to the first matching member rather than enforcingoneOf, so the generated Python models behave sensibly regardless. It was found while building a Go SDK from the same preprocessed schemas, where enforcingoneOfstrictly madeCart,CheckoutandOrderpermanently invalid.Related but distinct: ucp#615 also concerns
oneOfmember shapes, in the opposite direction —fulfillment_destination's members composepostal_addressinconsistently, forcing consumers to branch. This issue is about members that are indistinguishable. Both bear on whether aoneOf's alternatives are meaningfully different; neither fix addresses the other.