Skip to content

fleet(queue): repo-queue client accepts empty REPO_QUEUE_DEFAULT_QUEUE / REPO_QUEUE_SIGNAL_PATH — silently uses queue "" and fails signal writes with a blank path #6314

Closed

Description

@developing-today

fleet(queue): repo-queue client accepts empty REPO_QUEUE_DEFAULT_QUEUE / REPO_QUEUE_SIGNAL_PATH — silently talks to queue "" and fails signal writes with a blank path

Bug

In pkgs/fleet/crates/fleet-queue/src/client.rs (developing-today/code @ 6f5df296e2):

  • default_queue() (client.rs:585-587) returns std::env::var("REPO_QUEUE_DEFAULT_QUEUE") verbatim whenever the variable is set, falling back to DEFAULT_QUEUE only when it is unset:

    fn default_queue() -> String {
        std::env::var("REPO_QUEUE_DEFAULT_QUEUE").unwrap_or_else(|_| DEFAULT_QUEUE.to_string())
    }

    An exported-but-empty value (a common shell/systemd accident: REPO_QUEUE_DEFAULT_QUEUE= in an env file, an unset variable expanded by a wrapper) therefore becomes the queue name for every verb that goes through opt_queue() — list, enqueue, claim, signal, etc.

  • cmd_signal (client.rs:1257) has the same shape for REPO_QUEUE_SIGNAL_PATH: an empty value becomes the signal file path.

The same file already shows the intended pattern: direct_broker_url() (client.rs:69-76) trims REPO_QUEUE_BROKER_URL and treats empty as unset. The fleet-search client does the same for ATLAS_SEARCH_URL / ATLAS_SEARCH_TOKEN. These two sites were missed.

Evidence (verified this run, laptop primary @ 6f5df296e2; code identical at probe build)

Probe: ~/git/fleet/probe-queue-empty-env (laptop) — real repo-queue binary against a recording loopback stub broker (REPO_QUEUE_BROKER_URL=http://127.0.0.1:<port>, stub token file):

Case Request recorded at stub Client output
REPO_QUEUE_DEFAULT_QUEUE unset (control) POST /list {"queue":"repo-health-code-shadow",…} (no tasks)
REPO_QUEUE_DEFAULT_QUEUE= (empty) POST /list {"queue":"",…} (no tasks) — no error, no warning
REPO_QUEUE_DEFAULT_QUEUE=" " (whitespace) POST /list {"queue":" ",…} (no tasks) — no error, no warning
REPO_QUEUE_SIGNAL_PATH= (empty), signal --reason probe /signal-count posted normally exit 3, stderr: repo-queue: cannot write : No such file or directory (os error 2) — blank path in the message, signal file never written

So with an empty default-queue variable, an operator (or a fleet script) is silently shown an empty queue that is not the real queue, and an enqueue would be addressed to queue "" instead of the pilot queue — work addressed somewhere no worker claims, with no error anywhere. With an empty signal path, the wake-up signal that follows an enqueue dies with a message that names no path, so the failure is hard to trace back to the variable.

Why it matters

The repo-queue client is the fleet's control plane (producers enqueue, workers claim, signals wake workers). Its failure mode for a plausible configuration accident should be a loud usage error or the documented default — never silent redirection to a nonexistent queue. This is the same silent-misdirection class as #5939 (client parser silently overwriting/misreading flags, fixed) and the HOME-fallback filings #6238/#5640, but a distinct site and mechanism (env-var empty acceptance), not covered by either.

Acceptance criteria

  • REPO_QUEUE_DEFAULT_QUEUE set to empty or whitespace-only is treated as unset (fall back to DEFAULT_QUEUE), or rejected with a usage error naming the variable and its value — matching the direct_broker_url() trim-and-ignore-empty precedent in the same file; the chosen behavior is pinned by a test.
  • REPO_QUEUE_SIGNAL_PATH set to empty or whitespace-only gets the same treatment (default path or a named usage error); a signal write failure never reports a blank path.
  • Tests pin: unset → default; empty → default/error; whitespace → default/error; a normal value is used verbatim (trimmed per the broker-URL precedent).
  • Audit the client's remaining env reads (REPO_QUEUE_TOKEN_FILE, REPO_QUEUE_BROKER_URL — the latter already guards empty) for the same acceptance and note the result on this issue.
  • No behavior change when the variables are unset or set to ordinary values: list against the stub broker sends the same queue name as before.

Related

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    task/triageQueue packet kind: verify, reproduce, and route this item
    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
    ContributorAuthor

    🤖 Agent note · filed

  3. 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
  4. developing-today commented on Nov 5, 2026

    @developing-today
    ContributorAuthor

    🤖 Agent note · triaged — task 10612 (queue repo-health-code-pilot, lane code-h)

    • Verdict: CONFIRMED — both named sites, at current main c0b4ac62d1642826ba0b6681d394ba44667ea315 (fresh read of pkgs/fleet/crates/fleet-queue/src/client.rs on the laptop primary this triage; line numbers match the issue's exactly):
      1. default_queue() (client.rs:585–587): returns std::env::var("REPO_QUEUE_DEFAULT_QUEUE") verbatim whenever set — no trim, no empty check — so empty/whitespace becomes the queue name for every verb through opt_queue().
      2. cmd_signal (client.rs:1257): same shape for REPO_QUEUE_SIGNAL_PATH; an empty value becomes the signal file path and the write fails naming a blank path.
      3. Precedent verified in-file: direct_broker_url() (client.rs:69–76) trims REPO_QUEUE_BROKER_URL and treats empty as unset — the pattern these two sites missed.
    • Audit of the client's remaining env reads (acceptance criterion 4): client.rs reads exactly five env vars. HOME (client.rs:32, home()) is the distinct fleet(queue): repo-queue client resolves home-relative paths at the filesystem root when HOME is unset or empty — home() falls back to an empty string #6238 mechanism. REPO_QUEUE_BROKER_URL (client.rs:70) is already guarded. REPO_QUEUE_TOKEN_FILE (client.rs:94–95) has the SAME defect: it is used verbatim when set, so an empty value becomes token_file = "" and the read in direct_roundtrip fails with cannot read queue-broker token file : … — a blank path in the message and no fallback to the default token path. It is included in the follow-up fix scope. (Env reads in queue_broker.rs / secrets_broker.rs are separate server components, outside this issue's client scope — noted only.)
    • Fresh checks: issue fleet(queue): repo-queue client accepts empty REPO_QUEUE_DEFAULT_QUEUE / REPO_QUEUE_SIGNAL_PATH — silently uses queue "" and fails signal writes with a blank path #6314 is OPEN, no hard-stop labels (held / user/owned / do-not-merge / do-not-auto-edit), no covering PR (a search hit on PR fix(id): reject duplicate cli.commands and padded app-manifest list entries #4549 is unrelated and merged 2026-11-02, before this issue was filed). The creator's stub-broker probe evidence on the issue stands unrebutted and matches the code as read today.
    • Routing: follow-up small_fix task enqueued to repo-health-code-pilot (dedupe key repo-health:v1:fix:developing-today/code:issue:6314): apply the trim-and-treat-empty-as-unset pattern at all three sites, tests pinning unset/empty/whitespace/normal for each. Oracle: the direct_broker_url() precedent + the stub-broker invariant — empty/whitespace must behave exactly like unset.
  5. removed
    task/triageQueue packet kind: verify, reproduce, and route this item
    on Nov 5, 2026
  6. 9 remaining items

  7. added
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    queue/claimedQueue worker lifecycle state
    and removed
    queue/claimedQueue worker lifecycle state
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 5, 2026
  8. dezren39 commented on Nov 5, 2026

    @dezren39
    Member

    🤖 Agent note · picked up

  9. added a commit that references this issue on Nov 5, 2026
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 jobtask/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