Skip to content

Generated routed CLI prints raw ZodError JSON for input validation failures instead of a plain-language flag error #465

Description

@ScriptedAlchemy

Symptom in cargo-hauler

ScriptedAlchemy/cargo-hauler#47 — an agent ran the routed CLI with an out-of-range flag, hauler await cc-3178 --max-wait-ms 300000, and got:

[ { "origin": "number", "code": "too_big", "maximum": 55000, "inclusive": true, "path": ["maxWaitMs"], "message": "Too big: expected number to be <=55000" } ]
Run 'cargo-hauler await --help' for usage.

That is ZodError.message (zod 4 serialises the issues array as JSON) printed verbatim. The reporter's ask: "print the cap in plain words, not the raw zod payload — an agent reading "too_big" maximum 55000 has to guess that it's milliseconds and that the fix is to loop." Every routed CLI generated by agent-bundle has this failure mode for every schema violation; the route author cannot intercept it.

Root cause in agent-bundle (main 10a98a0fb)

  • packages/agent-bundle/src/build/entry-shell.ts:292-298 — the generated bin's parseInput does route.module.inputSchema.parse(input) and rethrows new CliInputError(error.message); for a ZodError that message is the JSON issues array.
  • packages/agent-bundle/src/cli-entry.ts:684-689runGeneratedCliEntry writes error.message to stderr followed by Run '<name> <path> --help' for usage. and exits 2. Nothing formats issues.
  • The same pattern is duplicated in packages/agent-bundle/src/test/cli.ts:236 and packages/agent-bundle/src/test/render.ts:747, so the test harness shows the same raw text.

zod@4.5.4 (already a dependency of both packages) ships z.prettifyError(error) / z.treeifyError, which render ✖ Too big: expected number to be <=55000 → at maxWaitMs.

Workaround currently in cargo-hauler

None possible at the route level; the schema .max(awaitMaxWaitMs) at src/lib/protocol-schemas.ts:361-366 is what the generated CLI reports. cargo-hauler mitigates by repeating the ceiling in the flag description (src/cli/await.tsx:31-33), which only helps if the agent reads --help.

Proposed fix

  • In entry-shell.ts parseInput (and the two harness copies), detect ZodError (error instanceof z.ZodError or 'issues' in error) and build the CliInputError message from the issues: one line per issue, --flag-name: <issue.message> using the CLI's kebab-case spelling of path (the generated command already knows the flag ↔ field mapping), followed by the existing Run … --help hint. Fall back to z.prettifyError when the path cannot be mapped.
  • Keep exit code 2 and the --json/--ndjson machine modes unchanged (or emit the issues array as JSON only in those modes).
  • Document the error shape in website/docs/{en,zh}/guide/authoring/cli* (routed CLI section).

Acceptance

  • <bin> await x --max-wait-ms 300000 prints --max-wait-ms: Too big: expected number to be <=55000 (or equivalent prose) plus the usage hint; no [ { "origin": … on stderr.
  • Multiple issues print one line each; the path is rendered as the CLI flag, not a JSON pointer.
  • runCliCommand in agent-bundle/test returns the same formatted text so plugin tests can assert on it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingmeta-frameworkAgent Bundle compiler-coupled meta-framework

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions