From 1e4ff4aa47a54a9532293d46ef14ec93098dd155 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 7 Apr 2026 16:25:57 +0200 Subject: [PATCH] :bug: Ignore Zone.js toString TypeError in uncaught error handler (#8804) Zone.js (injected by browser extensions such as Angular DevTools) patches addEventListener by wrapping it and assigning a custom .toString to the wrapper via Object.defineProperty with writable:false. When the same element is processed a second time, the plain assignment in strict mode (libs.js is built with a "use strict" banner) throws a native TypeError: "Cannot assign to read only property 'toString' of function '...'". This error escapes the React tree through the window error/unhandledrejection events and was surfacing the exception page to users even though Penpot itself is unaffected. The fix: - Extract the private ignorable-exception? helpers from the letfn block into top-level defn/defn- forms so the predicate can be reused elsewhere. - Add the Zone.js toString TypeError to the ignorable-exception? predicate so the global uncaught-error handler silently suppresses it. - The React error boundary is intentionally left unchanged: anything that reaches it has executed inside React's reconciler and must not be ignored. --- frontend/src/app/main/errors.cljs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/errors.cljs b/frontend/src/app/main/errors.cljs index 7671316589..5cc437e4a3 100644 --- a/frontend/src/app/main/errors.cljs +++ b/frontend/src/app/main/errors.cljs @@ -390,7 +390,16 @@ ;; RxJS unsubscription / take-until chain). These are ;; handled gracefully inside app.util.http/fetch and must NOT ;; be surfaced as application errors. - (= (.-name ^js cause) "AbortError")))) + (= (.-name ^js cause) "AbortError") + ;; Zone.js (injected by browser extensions such as Angular + ;; DevTools) wraps event listeners and assigns a custom + ;; .toString to its wrapper functions using + ;; Object.defineProperty. When the wrapper was previously + ;; defined with {writable: false}, a subsequent plain assignment + ;; in strict mode (our libs.js uses "use strict") throws this + ;; TypeError. This is a known Zone.js / browser-extension + ;; incompatibility and is NOT a Penpot bug. + (str/starts-with? message "Cannot assign to read only property 'toString'")))) (on-unhandled-error [event] (.preventDefault ^js event)