From 5931f60d5393ff50a89b4f8580730be08bc45d00 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 14 Sep 2026 13:25:31 +0200 Subject: [PATCH] :bug: Fix workspace crash when resolving thumbnail data URIs (#11563) The workspace-thumbnail-by-id ref unconditionally called resolve-media on thumbnail URIs, which caused a stack overflow when the URI was a data URI (which can be megabytes long for large images). Data URIs contain thousands of '/' characters (base64 uses '/' as one of its 64 characters), causing lambdaisland.uri/join to iterate thousands of times in remove-dot-segments and overflow the JavaScript call stack. Add a resolved-uri? helper that checks if the URI already starts with 'blob:' or 'data:', and skip resolve-media for those cases. Only call resolve-media when the URI is a plain UUID (media-id from the server). Closes #11562 AI-assisted-by: qwen3.7-plus --- frontend/src/app/main/refs.cljs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/refs.cljs b/frontend/src/app/main/refs.cljs index a73ae9b872..0dae7a5bfd 100644 --- a/frontend/src/app/main/refs.cljs +++ b/frontend/src/app/main/refs.cljs @@ -19,6 +19,7 @@ [app.main.store :as st] [app.main.streams :as ms] [beicon.v2.core :as rx] + [clojure.string :as str] [okulary.core :as l])) ;; ---- Global refs @@ -583,13 +584,21 @@ (dm/get-in state [:viewer-local :zoom-type])) st/state)) +(defn- resolved-uri? + "Returns true if the uri is already a fully resolved URI (blob or data)." + [uri] + (or (str/starts-with? uri "blob:") + (str/starts-with? uri "data:"))) + (defn workspace-thumbnail-by-id [object-id] (l/derived (fn [state] (when-let [entry (dm/get-in state [:thumbnails object-id])] (cond-> entry - (:uri entry) (update :uri cf/resolve-media)))) + (and (:uri entry) + (not (resolved-uri? (:uri entry)))) + (update :uri cf/resolve-media)))) st/state)) (def workspace-text-modifier