Guard Observer .observe() calls against broken browser stubs #SUPERLOG - #445
Guard Observer .observe() calls against broken browser stubs #SUPERLOG#445superlog-app[bot] wants to merge 1 commit into
Conversation
Delivery-Id: 3cf741aa53f16db54b0de632db02d442514ba66521319713654d75a79553e5d7 Delivery-Base: main
| try { | ||
| resizeObserver.observe(targetCanvas); | ||
| intersectionObserver.observe(targetCanvas); | ||
| } catch { |
There was a problem hiding this comment.
logs · warning — Log the caught observer error in FluidSignalField
Add a structured error log inside the catch block (including the caught exception) so operators can detect and scope broken-stub environments in production; without it the failure is completely invisible and the incident recurrence rate cannot be measured.
| } catch { | |
| } catch (err) { | |
| // Resize and intersection tracking unavailable; proceed without them. | |
| logger.error("observer.observe failed — resize/visibility tracking disabled", { error: err }); | |
| } |
Useful? React with 👍 / 👎.
| try { | ||
| observer.observe(node); | ||
| } catch { | ||
| setCount(ACCEPTANCE_RATE); |
There was a problem hiding this comment.
logs · warning — Log the caught observer error in AcceptanceStat
Add a structured error log inside the catch block (including the caught exception) so operators can correlate broken-stub occurrences with the vivid-hare incident and detect any new browser environments triggering the same fallback path.
| setCount(ACCEPTANCE_RATE); | |
| } catch (err) { | |
| logger.error("IntersectionObserver.observe failed — count-up animation skipped", { error: err }); | |
| setCount(ACCEPTANCE_RATE); | |
| return; | |
| } |
Useful? React with 👍 / 👎.
| try { | ||
| resizeObserver.observe(targetCanvas); | ||
| intersectionObserver.observe(targetCanvas); | ||
| } catch { |
There was a problem hiding this comment.
metrics · warning — Increment a counter when observer stubs are broken
Record a low-cardinality counter (e.g. browser_observer_stub_total with dimension component) in both catch blocks so the rate of affected sessions can be tracked over deployments and alerting thresholds can be set without log-mining.
Useful? React with 👍 / 👎.
Summary
The landing page at
superlog.shwas crashing with "Superlog hit an unexpected error" for visitors using browser environments (headless browsers, aggressive privacy extensions, or fingerprint-protection modes) whereIntersectionObserverandResizeObserverconstructors return stub objects that are missing the.observe()method.Root Cause
Two recently-added landing page components call
.observe()without guarding against broken observer instances:AcceptanceStat(added in Add acceptance-rate stat to the landing page #434) — creates anew IntersectionObserverand callsobserver.observe(node)in auseEffect. When the instance lacks.observe(), aTypeError: o.observe is not a functionis thrown.FluidSignalField(added in Redesign the landing hero with animated Slack cards #427) — creates both aResizeObserverandIntersectionObserverand calls.observe(targetCanvas)on each. The same broken-stub scenario throwsTypeError: Ct.observe is not a function.Both errors propagate to the
BrowserErrorBoundarywrappingMarketingApp, which replaces the entire page with the error fallback screen. Both issues were observed at the same timestamp (2026-08-01T07:58:38) from a single browser session on the latest deployment.Remediation
Wrapped the
.observe()calls intry/catchblocks in both components:FluidSignalField: if observing fails, the WebGL animation still runs — it just won't auto-resize or pause when scrolled out of view.AcceptanceStat: if observing fails, resets the count to the final value (90) so the stat still shows correctly without the count-up animation.The
.disconnect()cleanup calls are unaffected (they stay outside the try-catch and remain safe to call on any observer instance).Related incident: vivid-hare (666da96c-10fa-4683-8536-e743e1de2a13)
Was this PR helpful? Leave feedback — goes straight to the Superlog team.
Summary by cubic
Guarded
.observe()calls onIntersectionObserverandResizeObserverto prevent landing page crashes when browsers return broken stub instances. Users with headless or privacy-hardened setups now see the page; animations degrade gracefully instead of throwing.FluidSignalField: wrap.observe()in try/catch; animation continues without resize/visibility tracking.AcceptanceStat: wrap.observe()in try/catch; fall back to the final count when observing fails.Written for commit 909ca23. Summary will update on new commits.