Relationships
#3851 behavior validate gives pre-flight checks unparsed global arguments (no zod defaults), unlike behavior run
Opened by reset · 10/23/2026
On swamp 20261020.024627.0-sha.26dc044f (macOS 27), a behavior with globalArguments: z.object({ steamcmd: z.string().default("/opt/steamcmd/steamcmd.sh") }) and a check that reads context.globalArgs.steamcmd.includes("steamcmd") validates like this for an instance created with no --global-arg:
swamp behavior validate p1 --json ->
{ "name": "Check: needs-steamcmd", "passed": false, "error": "Cannot read properties of undefined (reading 'includes')" }
The same check passes when a method runs, because method execution parses the global arguments through the schema first ("Update definition with parsed values so methods receive correct types", method_execution_service.ts) and only then calls check.execute. The validation path (validation_service.ts, the check loop) sets let resolvedGlobalArgs = definition.globalArguments, resolves vault and env expressions, and passes that object as globalArgs without a schema parse, so zod defaults, coercions and transforms are absent. A check that works at run time therefore fails in CI, where validate is what runs, and the only fix an author has is to guard every defaulted field or drop the check.
Expected: validate gives a check the same globalArgs object the run path gives it: the definition values parsed through globalArguments (defaults applied, unresolved expression keys skipped, as the lenient parse in the run path does).
Actual: validate passes the raw definition values, so defaulted fields are undefined.
Steps to reproduce:
swamp repo init --tool none; addextensions/behaviors/probe.tsexporting a behavior with the schema and check above (appliesTo: ["upload"], methodupload).swamp behavior create @probe/thing p1 --json(no global args).swamp behavior validate p1 --jsonreports theTypeErrorabove;swamp behavior run p1 upload --jsondoes not.
#3196 (shipped) fixed validate checking global arguments without the upgrade chain; #1362 and #1453 (shipped) fixed checks receiving unresolved vault text. This is the remaining gap in the same path: the schema parse that run applies before checks. Running every check regardless of appliesTo when --method is not given is documented in the source as intended and is not asked here; --method <m> already scopes it.
Suggestion: apply parseGlobalArgumentsLeniently (or the same parse the run path uses) to resolvedGlobalArgs before building the check context, keeping unresolved keys skipped.
Open
No activity in this phase yet.
Sign in to post a ripple.