Skip to content

fleet(queue): repo-queue client parser silently overwrites duplicate flags, accepts --dry-run=false as true, and silently defaults a non-numeric --limit #5939

Closed

Description

@dezren39

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 for enqueue packet.json --queue alpha --queue beta --dry-run → the /enqueue body carried
    "queue": "beta". Root cause: opts.insert(name, …) overwrites
    (client.rs:487/490). A mistyped or script-concatenated second
    --queue silently 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": true and the client printed
    {"_dry_run": true, …}: nothing was enqueued, while the caller
    explicitly wrote false intending a real enqueue. Root cause:
    parse_args checks bools.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 --limit silently becomes the default.
    list --limit abc → exit 0, "(no tasks)"; the broker received
    "limit": 20. Root cause: get_i64 is parse().ok()
    (client.rs:521–523) and cmd_list does .unwrap_or(20). A typo'd
    limit is indistinguishable from asking for the default.
    (Contrast inside the same file: pos_i64 dies 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 via get_i64) with a
    non-numeric value is a usage error naming the flag and the value,
    matching the existing pos_i64 behaviour 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

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    task/small-fixQueue packet kind: bounded fix with reproduction and targeted tests
    source/creatorFiled by the new-issue-creator job
    priority/normalOrdinary priority (the default)
    queue/queuedHas a queued task in the Supabase agent queue
    app/fleetpkgs/fleet multicall binary + platform crates
    on Nov 5, 2026
  2. developing-today commented on Nov 5, 2026

    @developing-today
    Contributor
  3. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

  4. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed (evidence addendum, same run)

    • Agent: new-issue-creator job (new-issue-creator-code-a)
    • Session / ID: new-issue-creator-code-a run 2026-11-04 21:35 CST
    • Found via: filed this run
    • Task: Fourth shape of the same parser defect, verified with the same probe (~/git/fleet/probe-queue-args) minutes after filing: a value flag consumes the next flag token as its value. list --status --limit 5 → status takes --limit as its value, 5 becomes a positional, and the client dies with the misleading list: unexpected extra argument "5" (exit 2, no broker request made). Same for list --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.
    • Expectation: effort s (unchanged); add this shape to the pinning tests
    • Links: issue fleet(queue): repo-queue client parser silently overwrites duplicate flags, accepts --dry-run=false as true, and silently defaults a non-numeric --limit #5939; task 9839 already enqueued for it
  5. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 5, 2026
  6. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  7. added 2 commits that reference this issue on Nov 5, 2026
  8. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

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

    app/fleetpkgs/fleet multicall binary + platform crateskind/bugSomething isn't working (prefixed form of the classic bug label)priority/normalOrdinary priority (the default)source/creatorFiled by the new-issue-creator jobstatus:donetask/small-fixQueue packet kind: bounded fix with reproduction and targeted tests

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions