Relationships
#3873 workflow validate derives required arguments from zod's JSON Schema, so zod 4.6.7 rejects workflows that omit optional preprocess and catch arguments
Opened by zack · 10/23/2026· Shipped 10/23/2026
Description
swamp workflow validate decides which method arguments a step must supply from the required list of zod's JSON Schema (z.toJSONSchema(method.arguments, { io: "input" })). The only adjustment swamp makes is to drop fields whose property carries a default (stripDefaultsFromRequired in src/libswamp/types/schema_helpers.ts). The list is used in src/libswamp/workflows/validate.ts (both the definition path and resolveByType).
That list is not the same as "the arguments fail to parse without this field". It changes with the zod version, and zod 4.5+ (shipped by #3335, zod 4.6.7) changes it:
z.preprocess(fn, X)fields are now listed as required underio: "input", even whenfnturns a missing value into a valid one. 4.4.3 did not list them..catch()wrapped around a transform is now listed as required and loses itsdefault, so swamp's default-stripping no longer removes it.- Intersections (
a.and(b)) are merged into one object, so theirrequirednow reaches the top level. Under 4.4.3 they emittedallOfwith no top-levelrequired, and validate checked nothing for them.
The first two make validate reject workflows that run fine today. The third goes the other way: validate was under-reporting required arguments before.
Impact (registry scan, 4.4.3 vs 4.6.7)
All 1,209 third-party registry extensions and all first-party swamp-extensions behaviors were loaded under both zod versions and their schemas compared:
- 1 real regression:
@hivemq/asdlc, methodvalidate.noChange,planClaim,prUrl,ticketTitleandticketDescriptionare each az.preprocessthat turns a missing value intofalseor an empty string. Under 4.4.3 the arguments parse without them. Under 4.6.7 validate requires all five, so workflows that omit them would failswamp workflow validate. - 15 third-party extensions plus first-party typesafe-ai (
ask.questions,choice.criteria,score.criteria) newly report arguments that were already required at runtime (their parse fails or throws without them). Only the timing of the error changes.
Steps to Reproduce
- A behavior whose method arguments include
flag: z.preprocess((v) => v === true || v === "true", z.boolean()). - A workflow step that calls the method without
flag. - On zod 4.4.3 (stable today),
swamp workflow validatepasses and the run works:flagparses tofalse. - On zod 4.6.7 (main after #3335),
swamp workflow validatereportsflagas a missing required argument. The method still parses without it.
Expected
The required-argument check reflects what the arguments actually accept, whatever the zod version. A field is required only when the arguments fail to parse without it.
Suggested fix
Derive required arguments from zod rather than from JSON Schema required. For example:
- treat a top-level field as required only if parsing the arguments with that field absent produces an issue at that path, or
- read each field's own optionality from zod (
_zod.optin), and treatpreprocess/catchfields by whether they acceptundefined.
That fixes the preprocess and .catch() cases and keeps the (correct) intersection case. Ideally it also covers global arguments and the swamp-club#3681 transform handling, so the rule no longer depends on how a given zod version renders JSON Schema.
This should land before or with the zod 4.6.7 bump reaching stable. The release from #3335 has not been promoted: its UAT run was cancelled and revert #3336 is on hold.
Environment
- swamp
mainat 058c32be2 (zod 4.6.7) vs stable20261023.183232.0-sha.c0e1560b(zod 4.4.3) - Linux x86_64
Shipped
Click a lifecycle step above to view its details.
Sign in to post a ripple.