Version: 10.0.5 (also 10.0.3 / 10.0.4)
File: lib/valibot.ts:337-354 and :357-400
Summary
For an OpenAPI allOf whose members are objects, the valibot emitter writes v.intersect([strictObject(A), strictObject(B), …]). Because each strictObject independently rejects unknown keys, any value with properties from one member but not the other fails validation. With two disjoint-property members the schema rejects every possible value.
Minimal repro
OpenAPI (mirrors what @block65/openapi-constructs emits from Schema(..., { schema: { allOf: [...] } })):
components:
schemas:
Org:
type: object
required: [id, name]
properties:
id: { type: string }
name: { type: string }
UserMembership:
allOf:
- $ref: '#/components/schemas/Org'
- type: object
required: [role]
properties:
role: { type: string }
Generated valibot.ts:
export const orgSchema = v.strictObject({ id: v.string(), name: v.string() });
export const userMembershipSchema = v.intersect([
orgSchema,
v.strictObject({ role: v.string() }),
]);
Calling v.parse(userMembershipSchema, { id: "o1", name: "Acme", role: "admin" }) throws:
ValiError: Invalid key: Expected never but received "role"
ValiError: Invalid key: Expected never but received "id"
The first strictObject rejects role; the second rejects id and name. There is no input that satisfies both.
Expected
allOf of object schemas should be merged into a single v.strictObject with the union of properties (and union of required). The OpenAPI spec defines allOf as schema composition (logical AND), and every other major OpenAPI→validator toolchain (zod-openapi, openapi-zod-client, redocly, etc.) collapses allOf of objects into one merged object before emitting the closed-object validator.
Actual
lib/valibot.ts:342 unconditionally picks intersect for allOf, then :400 emits each object member as a strictObject. The two are incompatible in valibot — v.intersect([strictObject, strictObject]) is only viable if the property sets are identical.
Version: 10.0.5 (also 10.0.3 / 10.0.4)
File:
lib/valibot.ts:337-354and:357-400Summary
For an OpenAPI
allOfwhose members are objects, the valibot emitter writesv.intersect([strictObject(A), strictObject(B), …]). Because eachstrictObjectindependently rejects unknown keys, any value with properties from one member but not the other fails validation. With two disjoint-property members the schema rejects every possible value.Minimal repro
OpenAPI (mirrors what
@block65/openapi-constructsemits fromSchema(..., { schema: { allOf: [...] } })):Generated
valibot.ts:Calling
v.parse(userMembershipSchema, { id: "o1", name: "Acme", role: "admin" })throws:The first
strictObjectrejectsrole; the second rejectsidandname. There is no input that satisfies both.Expected
allOfof object schemas should be merged into a singlev.strictObjectwith the union of properties (and union ofrequired). The OpenAPI spec definesallOfas schema composition (logical AND), and every other major OpenAPI→validator toolchain (zod-openapi, openapi-zod-client, redocly, etc.) collapsesallOfof objects into one merged object before emitting the closed-object validator.Actual
lib/valibot.ts:342unconditionally picksintersectforallOf, then:400emits each object member as astrictObject. The two are incompatible in valibot —v.intersect([strictObject, strictObject])is only viable if the property sets are identical.