Repository navigation
Description
fleet(queue): the repo-queue client's parser silently overwrites duplicate flags, accepts --dry-run=false as true, and silently defaults a non-numeric --limit
Summary
The repo-queue / fleet queue client's hand-rolled argument parser
(pkgs/fleet/crates/fleet-queue/src/client.rs, parse_args, lines
471–512 at 1cf701651a) silently discards or misreads user input in
three ways. This is the #5713 / #5929 silent-flag-loss class on the
queue leaf: #5713 is scoped to fleet-dispatch and #5929 to
proxy connect; neither covers the queue client's own parser, which
every fleet lane uses to enqueue, claim, and complete work.
Evidence (verified this run, laptop, real binary built from HEAD)
Probe ~/git/fleet/probe-queue-args on the laptop: the freshly built
repo-queue binary (cargo build at 1cf701651a) driven against a
recording loopback broker (REPO_QUEUE_BROKER_URL +
REPO_QUEUE_TOKEN_FILE, the client's documented direct transport).
Recorded broker requests are the ground truth for what the parser
decided:
- Duplicate value flags last-win silently.
list --queue alpha --queue beta→ exit 0, no warning; the broker
received{"queue": "beta", …}. Same forenqueue packet.json --queue alpha --queue beta --dry-run→ the/enqueuebody carried
"queue": "beta". Root cause:opts.insert(name, …)overwrites
(client.rs:487/490). A mistyped or script-concatenated second
--queuesilently retargets work to the other queue. - A boolean flag ignores an inline value — including
=false.
enqueue packet.json --queue alpha --dry-run=false→ exit 0; the
broker received"dry_run": trueand the client printed
{"_dry_run": true, …}: nothing was enqueued, while the caller
explicitly wrotefalseintending a real enqueue. Root cause:
parse_argschecksbools.contains(name)before looking at the
inline=value(client.rs:485–488), so--dry-run=<anything>
means true. This is the dangerous direction: the verb reports
success for work it deliberately did not do. - A non-numeric
--limitsilently becomes the default.
list --limit abc→ exit 0, "(no tasks)"; the broker received
"limit": 20. Root cause:get_i64isparse().ok()
(client.rs:521–523) andcmd_listdoes.unwrap_or(20). A typo'd
limit is indistinguishable from asking for the default.
(Contrast inside the same file:pos_i64dies with a usage error
on an unparsable positional — the flag path has no such guard.)
Control case: list --queue alpha recorded exactly
{"queue": "alpha", "limit": 20, …} — single, well-formed flags
parse exactly as intended.
Why it matters
repo-queue is the fleet's work-order CLI: producers enqueue with it
and workers claim/checkpoint/complete through it, usually from
generated command lines where a duplicated or mistyped flag is a
realistic accident. Silent last-wins can enqueue or claim against the
wrong queue; --dry-run=false reporting success while enqueueing
nothing is a lost-work failure that no downstream check can see (the
queue simply never receives the task); a silently defaulted --limit
misreports queue depth to whoever is auditing it.
Acceptance criteria
- Repeating any value flag or boolean flag in one invocation is a
usage error (exit 2, naming the flag), for every verb — no silent
overwrite. - A boolean flag given an inline value (
--dry-run=false,
--dry-run=anything) is a usage error naming the flag; booleans
keep working in their bare form. --limit(and any other numeric flag read viaget_i64) with a
non-numeric value is a usage error naming the flag and the value,
matching the existingpos_i64behaviour for positionals.- Single well-formed invocations are byte-identical to today
(control case above stays green), and pinning tests cover the
three rejected shapes plus the control.
Notes
- Same bug class as fleet(dispatch): duplicate and contradictory flags silently resolved — repeated values overwrite, --no-* always beats --* #5713 (fleet-dispatch parser) and fleet(proxy):
proxy connectsilently overwrites duplicate flags and silently drops modes — repeated--host/--port/--request/--bodylast-wins,--stdioeats--request,--print-patheats--request,--host/--portwithout--stdioare no-ops #5929
(proxy-connect parser); the fix here is scoped to
fleet-queue/src/client.rs— a shared parser is a separate call. - Filed-only by the creator lane; not self-solved (the parser is
shared by all 15 queue verbs, so the rejection semantics deserve
the queue worker's normal review pass).
Activity
developing-today commentedon Nov 5, 2026
CODE-1611
dezren39 commentedon Nov 5, 2026
🤖 Agent note · filed
proxy connectsilently overwrites duplicate flags and silently drops modes — repeated--host/--port/--request/--bodylast-wins,--stdioeats--request,--print-patheats--request,--host/--portwithout--stdioare no-ops #5929 (proxy connect)dezren39 commentedon Nov 5, 2026
🤖 Agent note · filed (evidence addendum, same run)
list --status --limit 5→ status takes--limitas its value,5becomes a positional, and the client dies with the misleadinglist: unexpected extra argument "5"(exit 2, no broker request made). Same forlist --queue --status queued→unexpected extra argument "queued". The error names the wrong token: the real defect is at client.rs:491-495, where the next token is taken as a flag value without checking it is not itself a--flag. Worth covering in the same fix: a value flag whose next token starts with--should be a usage error naming the flag that is missing its value.dezren39 commentedon Nov 5, 2026
🤖 Agent note · picked up
test(fleet-queue): property-based tests for the parser invariants (#5939
Merge pull request #5941 from developing-today/queue/9839-5939-fleet-…
dezren39 commentedon Nov 5, 2026
🤖 Agent note · done
cargo test -p fleet-queue --features client --libon the laptop: 12 passed.