From 38a03830c2994742f567f95cc1bcedf97bdf5152 Mon Sep 17 00:00:00 2001 From: G30 <50341825+silentoplayz@users.noreply.github.com> Date: Tue, 11 Aug 2026 00:27:13 -0400 Subject: [PATCH] fix: show a placeholder when an image cannot be loaded (#27730) A message referencing a file that no longer exists rendered a broken image, because nothing anywhere noticed the failed load. What the user saw depended on the caller's alt text: in a response the alt is the message content, so the entire reply was rendered inside the image frame, and the preview still opened full-screen on a dead image. Image.svelte now tracks a failed load and renders an 'Image unavailable' placeholder instead, suppressing the preview for a source that cannot be shown. The failed state resets when the source changes, so a replaced or corrected URL is retried. An onError callback lets a caller react without changing behaviour for the eight existing call sites, which are untouched. Responses now pass the file name (or 'Generated Image') as alt rather than the message content, which was never a description of the image. --- .../chat/Messages/ResponseMessage.svelte | 2 +- src/lib/components/common/Image.svelte | 58 +++++++++++++++---- src/lib/i18n/locales/en-US/translation.json | 1 + 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/lib/components/chat/Messages/ResponseMessage.svelte b/src/lib/components/chat/Messages/ResponseMessage.svelte index df07c25f66..cf6973e98e 100644 --- a/src/lib/components/chat/Messages/ResponseMessage.svelte +++ b/src/lib/components/chat/Messages/ResponseMessage.svelte @@ -690,7 +690,7 @@ {#each message.files.filter((f) => ['image', 'file'].includes(f.type)) as file}
{#if file.type === 'image' || (file?.content_type ?? '').startsWith('image/')} - {message.content} + {file.name {:else} {}; + /** Called when the image fails to load, e.g. its file has since been deleted. */ + export let onError: () => void = () => {}; + const i18n = getContext('i18n'); let _src = ''; $: _src = safeImageUrl(src.startsWith('/') ? `${WEBUI_BASE_URL}${src}` : src, allowExternal); let showImagePreview = false; + + let failed = false; + let attemptedSrc = ''; + $: if (_src !== attemptedSrc) { + attemptedSrc = _src; + failed = false; + } + + const handleError = () => { + failed = true; + showImagePreview = false; + onError(); + }; - +{#if !failed} + +{/if}
- + {#if failed} +
+ + {$i18n.t('Image unavailable')} +
+ {:else} + + {/if} {#if dismissible}
diff --git a/src/lib/i18n/locales/en-US/translation.json b/src/lib/i18n/locales/en-US/translation.json index 1f15676d7f..8764964f6d 100644 --- a/src/lib/i18n/locales/en-US/translation.json +++ b/src/lib/i18n/locales/en-US/translation.json @@ -1406,6 +1406,7 @@ "Image Prompt Generation": "", "Image Prompt Generation Prompt": "", "Image Size": "", + "Image unavailable": "", "image/*, video/*": "", "Images": "", "Import": "",