Skip to content

feat(gmail): report how many results a search really has — resultSizeEstimate saturates at 201 and is unusable as a count #983

Description

@chrischall

Problem

gog gmail search and gog gmail messages search give a caller no way to learn how large a result set is without walking it. The JSON payload is items + nextPageToken, so "are there more?" is answerable but "how many more?" is not.

That gap causes a specific, repeatable failure in agent/LLM callers: a capped page gets read as the complete answer, and the caller reports that a message does not exist when it does. A page token alone is easy to skim past; a magnitude is not.

Why the obvious fix doesn't work

The Gmail API returns resultSizeEstimate on both users.threads.list and users.messages.list, and gog currently drops it — gmail_search.go:~97 and gmail_messages.go:~110 build the JSON payload by hand from items + nextPageToken.

Surfacing that field would be a bug, not a fix. It saturates. Measured on a live account, gog v0.35.0 (402def5), 2026-08-12:

$ gog api call gmail v1 users.messages.list \
    --params '{"userId":"me","q":"<Q>","maxResults":1,"fields":"resultSizeEstimate"}'
query resultSizeEstimate true count (--all)
from:freshbooks.com 201 21
from:housecallpro.com 201 6
from:thumbtack.com newer_than:30d 201 3
from:honeybook.com 201 9
invoice 201 >500
in:inbox 201 large
zzzznomatch 0 0

It returns 201 for every non-empty query and 0 for an empty one — a has-results boolean wearing a number's clothes. It is also independent of maxResults (identical at 1, 10, and 100), so it isn't a per-page figure either. Emitting it would let a caller report "3 of ~201" when the truth is 3 of 6.

Proposed fix

An opt-in --count flag on both search commands that reports a real number, obtained with one extra list call requesting a single maximal page of bare ids:

maxResults=500, fields="threads/id,nextPageToken"   (or messages/id)
  • fits in one page → exact total, emitted as totalMatches
  • fills the page with more behind it → honest lower bound, emitted as totalMatchesAtLeast

Verified against the same account:

query probe result matches --all?
from:freshbooks.com counted 21, no more pages ✅ 21
from:housecallpro.com counted 6, no more pages ✅ 6
invoice counted 500, more pages ✅ lower bound

The response is ids only, so it stays small, and the flag keeps it off the default path — no extra round-trip for callers who don't ask.

Exact whenever the set fits a page, which is the common case and always the case for the narrow queries a false negative is most likely to come from.

Notes

  • I have this implemented and validated in a downstream wrapper already; happy to send the --count PR here (branch in progress) if the shape looks right to you.
  • Open question for a maintainer: whether --count should also print on the text/table path, or stay JSON-only.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Low-risk cleanup, docs, polish, ergonomics, or speculative feature.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions