Skip to main content
← Back to list
01Issue
BugShippedSwamp CLI
Assigneesstack72

#316 swamp model create --global-arg KEY=VALUE doesn't coerce strings to z.number() schemas

Opened by bixu · 5/11/2026· Shipped 5/11/2026

Summary

swamp model create <type> <name> --global-arg KEY=VALUE always passes the value through as a string. When the model's globalArguments schema declares a numeric field with plain z.number(), the zod validator rejects it with expected number, received string and model creation fails. There is no way from the CLI to inject a non-string value for --global-arg (typed JSON payloads only exist for model method run --input).

Reproducer

Schema:

const GlobalArgsSchema = z.object({
  cpus: z.number().int().positive().default(4),
});

Invocation:

$ swamp model create "@example/repro" demo --global-arg "cpus=4" --json
{
  "error": "Invalid global arguments for type '@example/repro':\n  cpus: Invalid input: expected number, received string"
}

Expected

Either (a) the CLI parses bare numeric/boolean/JSON-ish values and passes them as the inferred type, or (b) the CLI coerces strings to the schema's declared primitive type before validation (effectively wrapping every leaf scalar in z.coerce.* on the way in). Today, extension authors have to opt into z.coerce.number() / z.coerce.boolean() everywhere a CLI user might set the field — the CLI ergonomics depend on the schema, which is leaky.

Workaround

Use z.coerce.number() (and z.coerce.boolean() etc.) in the extension's globalArguments schema. Discovered while building @hivemq/mudroom — the wrapper's swamp model create ... --global-arg cpus=4 --global-arg memoryMib=4096 was silently failing for first-time users (and CI), and the failure was hidden because the wrapper redirected swamp ... --json >/dev/null (the success-path stdout is just the JSON envelope).

Impact

  • First-time UX: any extension whose globalArguments has numeric/boolean fields is broken from the CLI unless the author knows to use z.coerce.*.
  • Wrapper authors: error messages get swallowed by >/dev/null of --json stdout, making the failure mode confusing.

References

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 4 MOREREVIEW+ 3 MOREPR_MERGEDSHIPPED

Shipped

5/11/2026, 1:45:55 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
stack72 assigned stack725/11/2026, 1:04:23 PM

Sign in to post a ripple.