Image messages stuck in "loading" state run an infinite CSS animation forever, causing sustained ~30% CPU usage
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 1.2k
- Forks
- 307
- Avg merge
- 17h 44m
- Merged PRs (30d)
- 256
Description
Environment:
- Wire webapp build:
app.js?v=2026-09-07.1-f1b2a6e(served fromapp.wire.com) - Client: wire-desktop 3.44.0 (Linux, Electron/Chromium), but reproducible in any browser since the bug is in webapp CSS/JS, not the Electron wrapper
- OS: Fedora Linux 44 (Workstation Edition), kernel 7.2.5-200.fc44.x86_64
Summary:
When an image message attachment fails to finish loading, the webapp leaves the message permanently in data-uie-status="loading" with its three-dot loading placeholder (.loading-dots.image-asset--no-image) instead of transitioning to the loaded image or an error state. The placeholder's threeLoadingDotsAni CSS animation has iteration-count: infinite, so it keeps running indefinitely — including while scrolled completely out of the viewport — driving continuous style recalculation and repaint even when the conversation is idle and the message isn't visible.
Impact:
Confirmed via Chrome DevTools Protocol profiling (Performance.getMetrics) on an idle client with two such stuck image messages present in one conversation:
RecalcStyleCount: 301 recalcs in 5 seconds (~60/sec, i.e. once per compositor frame)LayoutDuration: 0 (no reflow, just recalc/repaint)ScriptDuration: negligible (~0.01s / 5s) — the cost isn't application logic, it's the animation itself- Renderer process sustained ~27-30% of one CPU core continuously, confirmed via
/proc/<pid>/statutime+stime sampling, with zero change whether the window was focused, backgrounded, or minimized
Steps to reproduce:
- Receive or have in history an image message whose asset fails to load/decrypt (exact trigger for the initial failure wasn't isolated in this investigation — the bug here is what happens after it fails, not what causes the initial failure)
- Leave the conversation open with the failed image(s) present (loaded in the DOM, even if scrolled out of view)
- Observe: the message shows a permanent three-dot loading spinner (
aria-label="Image from <sender> from <time>",data-uie-status="loading") that never resolves - Profile the renderer (e.g.
chrome://inspector CDPPerformance.getMetrics) — observe continuous ~60Hz style recalculation and sustained CPU usage attributable to that element's animation, persisting indefinitely even when scrolled off-screen
Expected behavior:
An image asset that fails to load should time out into a visible error/retry state (and stop animating), not spin forever. At minimum, the loading animation should pause/stop for elements that are far outside the viewport (e.g. via content-visibility: auto or pausing Animation objects when off-screen), so a stuck placeholder doesn't burn CPU indefinitely in the background.
Actual behavior:
The placeholder animates forever at full frame rate regardless of visibility or load outcome, with no timeout or fallback UI, causing continuous unnecessary CPU usage for as long as the conversation stays open.
Additional notes:
wire-desktop sets backgroundThrottling: false on its BrowserWindow/webview, which means Chromium's usual throttling of animations/timers on hidden/backgrounded content doesn't apply here — so on desktop this bug's cost is paid continuously even while the app is minimized, not just while it's focused.
🤖 Generated with Claude Code
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating the image message handling for data-uie-status="loading", the .loading-dots.image-asset--no-image placeholder, and the threeLoadingDotsAni CSS animation in the webapp. Reproduce with a failed image and browser profiling, then verify that failures reach an error or retry state and that no indefinitely running animation continues, including for off-screen messages.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- css, typescript
- Domain
- frontend, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100