#16586

iTerm2 inline images leave stale content when redrawn at the same cursor position

Openlomavkinopened 9d ago

Pre-submit Checks

Describe the bug

When an application redraws an image at the same cursor position using the iTerm2 inline image protocol (OSC 1337;File=...), content from the previous image remains visible through transparent areas of the new image.

With the same reproduction in iTerm2, the previous content disappears.

I originally encountered this while using Serie: the initial graph looks correct, but scrolling causes old graph lines to accumulate instead of disappearing. The attached standalone Python script reproduces the behavior without Serie or any third-party dependencies.

Two videos demonstrate the minimal reproduction and the effect on Serie, comparing Warp with iTerm2.

To reproduce

Minimal reproduction with probe.py

Use the attached probe.py in an interactive terminal with at least 80 columns and 10 rows.

  1. Run:

    python3 probe.py --mode none
  2. Stage A displays an image with a red shape on the left and a transparent background.

  3. Press Enter. Stage B sends a second image at exactly the same cursor position and with the same display dimensions. It has a cyan shape on the right and a transparent background, including where the red shape was.

  4. In Warp, both the old red shape and the new cyan shape are visible. In iTerm2, only the cyan shape remains.

  5. Press Enter to exit.

As a comparison, run:

python3 probe.py --mode space

This writes 20 spaces starting at the image's anchor position, returns the cursor to the same position, and then sends the second image. In this case, the old red shape disappears in both terminals.

none and space are names used by the reproduction script, not options defined by the image protocol.

Both cases use the following image sequence:

ESC ] 1337;File=size=...;width=20;height=1;preserveAspectRatio=0;inline=1:BASE64 BEL

The script uses the alternate screen and synchronized updates. Both images are generated in memory and have identical dimensions.

probe.py

Reproduction with Serie

  1. Install Serie 0.10.0 and open a Git repository with branching history. The recordings use a checkout of warpdotdev/warp in both terminals.

  2. Run:

    serie -i head --protocol iterm
  3. Observe the initial graph, then scroll down repeatedly through the commit list, for example with Ctrl-E.

  4. In Warp, old graph lines remain and accumulate as the graph is redrawn. In iTerm2, the graph updates without the same accumulation of stale lines.

The --protocol iterm option explicitly selects the iTerm image protocol in both terminals.

Expected behavior

Expected behavior

Match iTerm2's (iTerm2 3.7.6) behavior for the minimal reproduction: after displaying image B, only the cyan shape should remain, with no red content from image A visible through B's transparent area.

In Serie, scrolling should update the graph without leaving lines from previously displayed graph images.

This expectation is based on comparison with iTerm2 itself. The published iTerm2 inline image protocol documentation does not explicitly specify replacement behavior for repeated images at the same position.

Actual behavior

TerminalRedraw without clearing (none)Write spaces before redraw (space)Serie scrolling
WarpOld red shape remainsOld red shape disappearsOld graph lines remain and accumulate
iTerm2Old red shape disappearsOld red shape disappearsNo equivalent accumulation of stale graph lines observed

Screenshots, videos, and logs

Minimal reproduction: probe.py

The video shows none followed by space in Warp, then the same two cases in iTerm2. Both modes use identical images; the difference is whether spaces are written before displaying image B.

  • Warp: the red shape remains with none, but disappears with space.
  • iTerm2: the red shape disappears in both cases.

https://github.com/user-attachments/assets/f3829e7a-e13d-4f3a-a3d2-7dc51a4601e5

Real-world example: Serie

The video shows Serie scrolling in Warp, followed by iTerm2, using the same repository and command:

serie -i head --protocol iterm

Warp retains old graph lines as the list scrolls, while iTerm2 redraws the graph without the same stale lines.

https://github.com/user-attachments/assets/94b92165-78a3-4224-87ac-42c6e87773ba

Both videos include terminal names, commands, and observations in English captions. The recorded terminal footage is played at its original speed.

Operating system (OS)

macOS

Operating system and version

macOS 15.7.3

Shell Version

zsh 5.9 (arm64-apple-darwin24.0)

Current Warp version

v0.2026.10.14.08.27.stable_02

Regression

No, this bug or issue has existed throughout my experience using Warp

Recent working Warp date

No response

Additional context

  • Originally observed in Serie 0.10.0 using its iTerm image rendering path.
  • The minimal reproduction does not involve scrolling: displaying two images at the same position is sufficient.
  • Serie sends graph images with transparent backgrounds. When a screen row is redrawn with a different graph image without first writing spaces at its anchor, this creates the same relevant conditions as the none case.
  • The minimal reproduction covers images with the same display dimensions. Replacement with different dimensions has not been verified.
  • Related: #7789 — Support placement IDs for kitty images. That issue describes a similar stale-image symptom, but concerns Kitty image/placement IDs. This report concerns the iTerm2 inline image protocol.

Does this block you from using Warp daily?

Yes, this issue prevents me from using Warp daily.

Is this an issue only in Warp?

Yes, I confirmed that this only happens in Warp, not other terminals.

Warp Internal (ignore): linear-label:b9d78064-c89e-4973-b153-5178a31ee54e

None

Activity

2
warp-for-oss[bot]9d ago

@lomavkin

Here's what I found while triaging this issue:

Thanks for the detailed reproduction and comparison videos. This looks like a Warp iTerm2 inline-image redraw bug rather than a Serie-specific issue; the spaces workaround is consistent with Warp clearing existing image placements for normal text writes but not when a replacement image is drawn at the same anchor.

Maintainer details

I concluded that warp leaves stale iTerm2 inline-image content visible when a transparent replacement image is redrawn at the same cursor position..

Triage summary

This is a terminal rendering bug in Warp's iTerm2 inline image handling. The report is well specified: it includes a minimal OSC 1337;File=... reproduction, Warp/iTerm2 comparison videos, a real-world Serie example, and environment details.

Reproducibility

High. The minimal reproduction sends two transparent inline images with identical display dimensions at the same cursor position. Warp leaves pixels from the first image visible through transparent areas of the second image, while iTerm2 does not. The --mode space comparison is especially useful because writing spaces first clears the stale placement in Warp.

Likely root cause

Warp's iTerm image path stores each received inline image with a generated image id and adds a placement at the current cursor point. The placement path does not appear to evict prior iTerm image placements at that same anchor or across the replacement image's occupied cell range. Separately, normal character writes call image eviction at the cursor cell, and clear-line/clear-screen paths evict iTerm image placements over cleared ranges. That matches the observed behavior: a direct redraw layers the new transparent image over the old placement, while writing spaces first clears the old placement before the new image is placed.

Relevant areas to inspect:

  • crates/warp_terminal/src/model/grid/ansi_handler.rs — completed iTerm image placement and text/clear eviction behavior
  • crates/warp_terminal/src/model/image_map.rs — placement indexing and eviction helpers
  • crates/warp_terminal/src/model/iterm_image.rs — iTerm image metadata and generated ids
  • app/src/terminal/model/terminal_model.rs — completed image decode/metadata flow

Duplicate check

I did not find two matching duplicate issues. Related issue #7789 concerns Kitty placement-id replacement semantics, and #1693 is broader iTerm inline image support, but this report is specifically about iTerm2 OSC 1337 redraw behavior with transparent replacement images.

This is my automated analysis and may be incorrect. A maintainer will verify the details.

Powered by Oz

lomavkin9d ago

@vorporeal

I already have a fix and tests ready, so would it be okay with you if I opened a PR for it?