Skip to content

fix: prevent error toasts from overflowing the viewport#9921

Open
henrytran1803 wants to merge 2 commits intowarpdotdev:masterfrom
henrytran1803:henrytran1803/fix-toast-stack-overflow
Open

fix: prevent error toasts from overflowing the viewport#9921
henrytran1803 wants to merge 2 commits intowarpdotdev:masterfrom
henrytran1803:henrytran1803/fix-toast-stack-overflow

Conversation

@henrytran1803
Copy link
Copy Markdown

Description

Error toasts (e.g. from repeated session share failures) could accumulate without bound, causing the toast stack to overflow the visible window with no way to scroll or dismiss older toasts.

The fix applies a three-layer defense:

  1. Cap persistent toast count (MAX_PERSISTENT_TOASTS = 5): When the limit is exceeded, the oldest toast is evicted from the stack.
  2. Deduplication by object_id: show_persistent_toast() now sets an object_id based on the toast text, so repeated identical error messages replace older toasts instead of stacking. The existing dismiss_older_toasts mechanism handles this automatically.
  3. Layout safety net (ConstrainedBox + Clipped): The rendered toast stack is constrained to a 500px max height with clipping, ensuring toasts never overflow the viewport even in edge cases.

Changes

  • app/src/view_components/dismissible_toast.rs:
    • Add MAX_PERSISTENT_TOASTS constant (5) and TOAST_STACK_MAX_HEIGHT constant (500px)
    • Cap persistent toast count in add_persistent_toast() by removing oldest toasts when limit exceeded
    • Wrap toast stack render in ConstrainedBox with Clipped to prevent viewport overflow
  • app/src/terminal/view.rs:
    • Add object_id to persistent toasts in show_persistent_toast() for deduplication

Linked Issue

Testing

The fix is defensive — it caps count, deduplicates, and constrains layout. Manual verification:

  • Repeatedly trigger session share failures → older duplicate toasts are replaced (dedup)
  • After 5+ unique persistent toasts → oldest evicted (cap)
  • Toast stack never exceeds 500px height (layout constraint)

No automated test was added because the toast stack depends on UI rendering infrastructure that requires the full Warp app bootstrap. The logic changes (cap + dedup) are straightforward guards that are easy to verify visually.

Co-Authored-By: Warp agent@warp.dev

Persistent error toasts (e.g. from repeated session share failures) could
accumulate without bound, causing the toast stack to overflow the visible
window with no way to scroll or dismiss older toasts.

Three-layer defense:
1. Cap persistent toast count at 5 — oldest toasts are evicted when exceeded
2. Deduplicate by object_id — repeated identical error messages replace
   older toasts instead of stacking
3. Constrain rendered toast stack to 500px max height with clipping as a
   layout safety net

Fixes warpdotdev#9733
@cla-bot cla-bot Bot added the cla-signed label May 2, 2026
@github-actions github-actions Bot added the external-contributor Indicates that a PR has been opened by someone outside the Warp team. label May 2, 2026
@henrytran1803 henrytran1803 marked this pull request as ready for review May 2, 2026 17:02
@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 2, 2026

@henrytran1803

I'm starting a first review of this pull request.

You can view the conversation on Warp.

I reviewed this pull request and requested human review from: @warpdotdev/oss-maintainers.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

This PR caps and deduplicates persistent toasts and adds a render-time max-height clipping guard to keep the toast stack from overflowing the viewport.

Concerns

  • No blocking correctness or security concerns found in the annotated diff.

Verdict

Found: 0 critical, 0 important, 0 suggestions

Approve

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

@oz-for-oss oz-for-oss Bot requested review from a team and vkodithala and removed request for a team May 2, 2026 17:08
Copy link
Copy Markdown

@RokeJulianLockhart RokeJulianLockhart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Cap persistent toast count (MAX_PERSISTENT_TOASTS = 5): When the limit is exceeded, the oldest toast is evicted from the stack.

@henrytran1803, that might be problematic if more than 5 unique toasts are rendered. (Is having them be scrollable infeasible?)

  1. Deduplication by object_id: show_persistent_toast() now sets an object_id based on the toast text, so repeated identical error messages replace older toasts instead of stacking. The existing dismiss_older_toasts mechanism handles this automatically.

Rendering a counter, for each time a duplicate toast is replaced, so that the user knows how many times that toast has been produced, would be helpful.

  1. Layout safety net (ConstrainedBox + Clipped): The rendered toast stack is constrained to a 500px max height with clipping, ensuring toasts never overflow the viewport even in edge cases.

Can we not, instead, calculate the geometry of the interface, rather than define an arbitrary constant? This might not be sufficient on low-DPI (1 024 × 720 px) displays:

- Remove arbitrary MAX_PERSISTENT_TOASTS cap; instead allow unlimited
  unique toasts with viewport-based height constraint
- Add duplicate counter: repeated identical toasts increment a count
  displayed as '(x3)' in the toast text instead of replacing silently
- Replace hardcoded 500px max height with computed viewport height
  from TAB_CONTENT_POSITION_ID element geometry, ensuring correct
  behavior on all display sizes including low-DPI
@henrytran1803
Copy link
Copy Markdown
Author

@RokeJulianLockhart great points, all three — pushed a fix that addresses each of them!

1. Scrollable instead of capped — yep, agreed. I dropped the MAX_PERSISTENT_TOASTS cap entirely. Now the toast stack is just constrained to whatever vertical space the tab content actually has, so all unique toasts stay visible (and don't get silently evicted).

2. Counter for duplicates — nice idea! Instead of replacing the duplicate, I now increment a counter on the existing toast and display it as (x3) in the text. That way the user can see something's going wrong repeatedly without the toast stack growing.

3. Viewport geometry instead of 500px — good catch on low-DPI, that would've been embarrassing 😅 Replaced the hardcoded constant with a computed height from TAB_CONTENT_POSITION_ID's actual rect (height - 32px for margins). Should scale correctly on any display size now.

Let me know if anything else needs tweaking!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed external-contributor Indicates that a PR has been opened by someone outside the Warp team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error toasts can render outside of the viewport, without a way to scroll them.

2 participants