Skip to content

0.14.0 – Images flicker / disappear when using Handle::from_bytes with active subscription #3160

@mxnt10

Description

@mxnt10

Is your issue REALLY a bug?

  • My issue is indeed a bug!
  • I am not crazy! I will not fill out this form just to ask a question or request a feature. Pinky promise.

Is there an existing issue for this?

  • I have searched the existing issues.

Is this issue related to iced?

  • My hardware is compatible and my graphics drivers are up-to-date.

What happened?

This issue did not occur in iced 0.13.1 and started happening in iced 0.14.0.

simplescreenrecorder-2025-12-21_16.53.31.mp4

When a subscription (such as event::listen()) is enabled and the application starts, the image initially renders correctly. However, as soon as window events begin to flow (for example, moving the mouse or triggering redraws), the image starts to flicker or completely disappear.

If the subscription is disabled, this behavior does not occur and the image remains stable.

The issue happens when loading images using Handle::from_bytes, especially when the handle is recreated during frequent view() calls triggered by subscriptions.

Details:

  • NVIDIA graphics card with up-to-date proprietary drivers
  • System running under an X11 session
  • Vulkan support

Minimal Example

[package]
name = "iced-image-bytes-mre"
version = "0.1.0"
edition = "2024"

[dependencies]
iced = { version = "0.14.0", features = ["image"] }
use iced::widget::image::Handle;
use iced::widget::{Column, Image, column};
use iced::{ContentFit, Element, Event, Subscription, Task, event};

pub fn main() -> iced::Result {
    // Start an iced application using the functional API.
    // State type: u64
    // update() is called for every incoming Message.
    // view() is called after each update.
    iced::application(u64::default, update, view)
        // Enabling this subscription is sufficient to trigger the issue.
        // When active, the image may flicker or temporarily disappear.
        .subscription(subscription)
        .run()
}

#[derive(Debug, Clone)]
enum Message {
    // All window/system events are forwarded here
    EventOccurred(Event),
}

fn update(_value: &mut u64, message: Message) -> Task<Message> {
    match message {
        // Even though no state is changed here,
        // receiving frequent events causes continuous update/view cycles.
        Message::EventOccurred(_event) => Task::none(),
    }
}

fn subscription(_state: &u64) -> Subscription<Message> {
    // Listen to ALL window events:
    // mouse movement, redraw requests, focus changes, resize, etc.
    // This results in view() being called many times per second.
    let subscriptions = vec![
        event::listen().map(Message::EventOccurred)
    ];

    Subscription::batch(subscriptions)
}

fn view(_value: &u64) -> Column<Message> {
    // The image file is read from disk every time view() is called.
    // With an active subscription, this happens very frequently.
    let path = std::path::PathBuf::from("assets/image.png");

    let icon_widget: Element<Message> = match std::fs::read(&path) {
        Ok(bytes) => {
            // IMPORTANT:
            // A NEW image Handle is created on every view() call.
            //
            // In iced 0.14.0, Handle::from_bytes() appears to not have
            // a stable identity across calls.
            // Each call seems to be treated by the renderer
            // as a completely new image resource.
            //
            // This suggests that the internal image/texture cache
            // may continuously drop and recreate the GPU texture
            // when view() is re-executed frequently.
            //
            // This behavior appears to be the cause of the
            // flickering / temporary disappearance of the image,
            // especially when subscriptions are active.
            //
            // NOTE:
            // This behavior did NOT occur in iced 0.13.1,
            // which suggests a possible regression in iced 0.14.0.
            let handle = Handle::from_bytes(bytes);

            Image::new(handle)
                .content_fit(ContentFit::ScaleDown)
                .width(512)
                .height(512)
                .into()
        }
        Err(_) => iced::widget::text("").into(),
    };

    // A new widget tree is returned on every call
    column![
        icon_widget,
    ]
        .into()
}

What is the expected behavior?

As in iced 0.13.1, images should not flicker or disappear when a subscription is enabled.

Version

master

Operating System

Linux

Do you have any log output?

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions