Skip to content

atlas-search(service): results-paging loop has no deadline or cursor-progress guard — a non-advancing page stream hangs the CLI forever instead of falling back to standalone #5424

Closed

Description

@dezren39

Bug

The via-service client's results-paging loop has no deadline and no progress guard (pkgs/atlas-search/crates/atlas-search/src/service.rs, search()):

loop {
    // GET {job_url}/results?limit=50[&cursor=...]
    ...
    results.extend(page.results.iter().cloned());
    if results.len() >= request.k || page.next_cursor.is_none() {
        break;
    }
    cursor = page.next_cursor;
}

The poll loop directly above it in the same function is deadline-disciplined (CLIENT_DEADLINE, 330 s, checked every iteration, service.rs:148 and :177). The paging loop checks nothing: if a page stream keeps returning a next_cursor without the collected results reaching request.k — a repeating cursor, an empty page with a cursor, a future server/protocol bug — the client loops forever, growing results unboundedly. The ureq agent's timeout_global is per-request, so it does not bound the loop.

Why it matters

The module's stated contract (service.rs:1-13) is prefer service, fall back to standalone loudly: "any failure — unreachable, an HTTP error, a failed/expired job, a malformed response — is reported by the caller on stderr and recorded in the envelope's notes, and standalone serves the query." A non-advancing page stream is exactly the malformed-response case that contract exists for, but instead of falling back the CLI hangs forever with no output and no error. Today's server advances cursors by construction (page() in server.rs encodes a strictly increasing offset), so this needs a server-side bug or a protocol change to bite — the client's own contract says it should not depend on that.

Evidence (verified this run, main d4539fc)

  • Code reading: the poll loop (service.rs:~148-185) carries deadline and returns Err("service job did not complete within 330 seconds"); the paging loop (service.rs:~190-222) has no Instant check, no comparison of the new cursor against the previous one, and no cap on pages or collected results.
  • The only exits from the paging loop are results.len() >= request.k, next_cursor.is_none(), or an HTTP/parse error — none of which a well-formed-but-non-advancing page stream triggers.

Acceptance criteria

  • The paging loop honors the same 330 s client deadline as the poll loop and returns an Err (triggering the caller's loud standalone fallback) when it expires mid-paging.
  • A page whose next_cursor does not advance (equal to the cursor just used), or an empty page that still returns a cursor, is treated as a malformed response: Err, not another iteration.
  • A unit/integration test with a stub service returning a repeating cursor shows search() returning Err promptly instead of looping; the normal multi-page happy path (more results than one page, k reached mid-stream) is unchanged.
  • cargo test -p atlas-search green (run on the laptop or CI per fleet norms).

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/atlas-searchpkgs/atlas-search (Atlas search service + atlas-embed)
    on Nov 4, 2026
  2. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

    • Agent: new-issue-creator job (new-issue-creator-code-a)
    • Session / ID: cron new-issue-creator-code-a, run 2026-11-04T11:47Z
    • Found via: filed this run
    • Task: Filed after verifying on main d4539fc that the via-service client's paging loop (service.rs search()) has no deadline and no cursor-progress check, unlike the deadline-disciplined poll loop in the same function; packet enqueued for a small fix.
    • Expectation: effort/s — done when paging honors the 330 s client deadline and a non-advancing/empty cursor page returns Err (loud standalone fallback), with a repeating-cursor stub test.
    • Links: body evidence in the issue; queue packet packet-5424-fix.json
  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 4, 2026
  4. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

    • Agent: repo queue worker, lane code-x (task 9435)
    • Session / ID: cron repo-queue-worker-shift-x, run 2026-11-04T11:59Z
    • Found via: claimed task 9435 from repo-health-code-pilot queue
    • Task: Bound the atlas service client's results-paging loop (deadline + cursor-progress guard) with a repeating-cursor stub test.
    • Expectation: effort/s — PR opened and task completed when paging honors the client deadline and non-advancing/empty cursor pages return Err.
  5. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

    • Agent: repo queue worker, lane code-x (task 9435)
    • Session / ID: cron repo-queue-worker-shift-x, run 2026-11-04T11:59Z
    • Found via: claimed task 9435 from repo-health-code-pilot queue
    • Task: Bound the atlas service client's results-paging loop (deadline + cursor-progress guard) with a repeating-cursor stub test.
    • Result: PR atlas-search(service): bound the results-paging loop — deadline + cursor-progress guard (#5424) #5437 merged (squash 06fcdb6). Paging loop honors the same 330 s client deadline as the poll loop; a non-advancing next_cursor or an empty page still returning a cursor is a malformed response returning Err (loud standalone fallback). Stub-service tests: repeating cursor returns Err promptly, empty page with cursor returns Err, multi-page happy path unchanged. cargo test -p atlas-search green on the laptop; Codex review completed with no findings; basic CI checks passed.
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/atlas-searchpkgs/atlas-search (Atlas search service + atlas-embed)kind/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