# 02-Jul-2026 — self-heal expired Gmail history cursor and surface sync errors [#293](https://github.com/nbarrett/ngx-ramblers/issues/293)

## [build 725](https://github.com/nbarrett/ngx-ramblers/actions/runs/28560303316) — [commit 1500fce](https://github.com/nbarrett/ngx-ramblers/commit/1500fcec36c4592a617ae201a6bbbaffb5b96f3a)

_____

## What's new

When Gmail's history.list returns 404 "Requested entity was not found" (the stored historyId has expired), the poller now resets the cursor and falls back to a full listing instead of leaving the connection wedged in an error state with no recovery. This is Gmail's documented behaviour for an expired history cursor and the fix protects every connected inbox, not just one. Alongside this, the connected-mailbox card in system settings now shows a warning when the connection is in the error state (previously only the token-revoked case was shown), pointing at the re-scan action, so a stuck sync is visible with its reason instead of silently importing nothing.

## At a glance

- Gmail inbox syncs recover by themselves after an expired history cursor instead of staying stuck and importing nothing.
- The connected-mailbox card shows a "Mail is not importing" warning with the last error message whenever the connection is in an error state.
- The warning points to the "Re-scan general mailbox from scratch" action if the sync does not recover on its own.

## Technical changes

- Expired-history detection matches "requested entity was not found", a 404 code in the error body, or FAILED_PRECONDITION; any other error is rethrown, and recovery clears the stored lastHistoryId then retries via the full-listing path within the same poll.
- Outbound messages in the inbox thread view are labelled "Sent from Email Composer — <sender>" (previously "Sent from this group"); replies sent from an external client carry no label because they never pass through NGX.
- Thread-view layout tweaks: Reply/Reply all buttons inset from the top of the message container, collapsed headers get the full row width (the buttons only take space while hovering), and collapsed previews carry up to 500 characters with the CSS truncation clipping to the available width.