Skip to content

gl renders node denials as empty lists / silent success across list commands #397

Description

@Gravirei

What happened?

gl list/show commands ignore the HTTP status code and map any denial body (403/404) to an empty list with exit 0. A caller who may not read a repo (or hits a withheld subtree / revoked access / dead node) sees “No …” / 0/0/0 / stub ? output instead of the denial. This turns an authorization boundary into invisible data loss.

Per AGENTS.md > Client behavior: “When a node denies a request, surface the denial to the user. Never render a denial as an empty list or a silent success.”

Affected paths (all Ok(()), no status.is_success() check before .json() + unwrap_or_default()):

  • crates/gl/src/status.rs:84-86 (prs = body["pulls"]…unwrap_or_default() → “no open pull requests”), 111-113 (issues, same)
  • crates/gl/src/issue.rs:224-231 cmd_list → “No issues for {owner}/{name}”; 347-365 cmd_issue_comments → “No comments on issue {id}”
  • crates/gl/src/pr.rs:252-264 cmd_list → “No pull requests”; 296-321 cmd_view → stub card ? (title/status unwrap_or("?") on error body); 324-332 reviews / 357-365 comments silently omitted; 384-398 cmd_diff → “No diff (branches may be identical…)”
  • crates/gl/src/bounty.rs:234-255 cmd_list → silent Ok(()), prints nothing (body["bounties"] is None on 403); 384-396 cmd_statsopen: 0 / claimed: 0 / completed: 0
  • crates/gl/src/task.rs:169-276 all commands print_json(&resp) without status check, so {"message":"…"} prints as if data (self-documented in tests at task.rs:361,451)
  • crates/gl/src/cert.rs:103-110 cmd_list → “No ref certificates”
  • crates/gl/src/repo.rs:280-286 cmd_list (403 body fails as_array context as opaque “expected array”, hides 403/404), 524-531 commits → “No commits”
  • crates/gl/src/peer.rs:66-73 cmd_list → “No known peers”; 259-264 ping / 284-289 resolve → ?/unreachable with Ok
  • crates/gl/src/node.rs:177-183 try_get_json drops non-2xx to None → “unavailable”, always Ok
  • crates/gl/src/clone.rs:320-326 recover_encrypted_blobs: any non-2xx → Ok(vec![]), caller prints Done. Cloned… / Recovered N files short with no warning
  • crates/gl/src/whoami.rs:52-56 nested repos fetch ignores status, silently omits count

Contrast: sibling commands in the same files do it correctly and prove the intended pattern — e.g. issue.rs:270 cmd_show, bounty.rs:265 cmd_show / 295 cmd_claim, cert.rs:147 cmd_show (.error_for_status()), repo.rs:354 cmd_info / 682 cmd_label_list all bail!("… ({status}): {msg}").

Expected behavior

On non-2xx, gl should surface the denial and exit non-zero, e.g. bail!("list failed ({status}): {msg}") using the already-established pattern from cmd_show/cmd_claim, never unwrap_or_default() to empty. gl status should print e.g. PRs ✗ denied (403) rather than no open pull requests.

Steps to reproduce

  1. mockito (or any stub) returning 403 {"message":"forbidden"} for a list route, e.g.:
    GET /api/v1/repos/{owner}/{repo}/issues → 403
  2. gl issue list --repo myrepo --node $MOCK → prints No issues for …, exit 0 (see issue.rs:231-235; same shape for gl pr list, gl bounty list, gl cert list, gl peer list).
  3. GET /api/v1/bounties/stats → 403 + gl bounty stats → prints open: 0 / claimed: 0 / completed: 0, exit 0.
  4. Revoke read on a private repo (or stop node) + gl clone with encrypted blobs → Ok(vec![]) at clone.rs:325, missing files reported as success.

Affected crate

gl

Version or commit

bfc44f92 (main, upstream/main @ 2026-09-05)

Environment

Linux, rustc 1.97.1, workspace gl CLI against any node returning non-2xx.

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

    crate:glgl — the contributor CLIkind:bugDefect fix — wrong or unsafe behaviorsev:mediumDegraded but workaround existssubsystem:apiNode REST API request/response surface

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions