{"record":{"id":"30b69d97464666ca","repo":"gitbutlerapp/gitbutler","slug":"window-resizeobserver-is-missing","errorCode":null,"errorMessage":"window.ResizeObserver is missing.","messagePattern":"window\\.ResizeObserver is missing\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ui/src/lib/components/scroll/Scrollbar.svelte","lineNumber":148,"sourceCode":"\n\t/////////////////////\n\t// VIEWPORT EVENTS //\n\t/////////////////////\n\tfunction onViewportMouseEnter() {\n\t\tif (!shouldShowOnHover) return;\n\t\tvisible = true;\n\t}\n\n\tfunction onViewportMouseLeave() {\n\t\tif (!shouldShowOnHover) return;\n\t\tvisible = false;\n\t}\n\n\tfunction setupViewport(viewport: Element) {\n\t\tif (!viewport) return;\n\n\t\tif (typeof window.ResizeObserver === \"undefined\") {\n\t\t\tthrow new Error(\"window.ResizeObserver is missing.\");\n\t\t}\n\n\t\tconst observerSize = new ResizeObserver(() => {\n\t\t\tupdateTrack();\n\t\t});\n\t\tobserverSize.observe(viewport);\n\n\t\tconst content = viewport.children.item(0);\n\t\tif (!content) {\n\t\t\tthrow new Error(\"Expected to find content container\");\n\t\t}\n\n\t\t// Sometimes the content size changes before the browser fires a\n\t\t// scroll event, so we compensate here to avoid thumb jumpiness.\n\t\t// However, if viewport.scrollTop has already been adjusted by\n\t\t// another component (e.g. VirtualList's scroll compensation),\n\t\t// we must use the actual value to avoid double-compensating.\n\t\tconst observerContentSize = new ResizeObserver(() => {","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/packages/ui/src/lib/components/scroll/Scrollbar.svelte#L130-L166","documentation":"Scrollbar.svelte's setupViewport requires window.ResizeObserver to observe the viewport element's size changes and keep the scrollbar thumb in sync. If ResizeObserver is undefined the component throws immediately during viewport setup rather than silently producing a broken scrollbar.","triggerScenarios":"The Scrollbar component is mounted in an environment without ResizeObserver: very old browsers (IE11, old Safari <13.4), non-browser jsdom-based test environments without the polyfill, or sandboxed webviews lacking the API.","commonSituations":"Unit tests rendering Svelte components in jsdom without a ResizeObserver polyfill; legacy embedded browsers; SSR/hydration setups where window is stubbed incompletely.","solutions":["Add a ResizeObserver polyfill (e.g. resize-observer-polyfill) to the app entry point.","Upgrade or configure the target browser/webview to one supporting ResizeObserver.","In tests, stub global.ResizeObserver with a no-op class before mounting the component.","Alternatively, patch Scrollbar.svelte to fall back to window resize + interval polling when the API is absent.","Feature-detect before mounting Scrollbar and skip custom scrollbars on unsupported platforms."],"exampleFix":"// before (test setup)\nimport { render } from \"@testing-library/svelte\";\n// after\nglobal.ResizeObserver = global.ResizeObserver || class { observe(){} unobserve(){} disconnect(){} };\nimport { render } from \"@testing-library/svelte\";","handlingStrategy":"fallback","validationCode":"if (typeof window === \"undefined\" || typeof window.ResizeObserver === \"undefined\") {\n  // skip custom scrollbar or load polyfill first\n  import(\"resize-observer-polyfill\").then((RO) => { (window as any).ResizeObserver = RO.default; });\n}","typeGuard":"function hasResizeObserver(w: Window): w is Window & { ResizeObserver: typeof ResizeObserver } {\n  return typeof (w as any).ResizeObserver === \"function\";\n}","tryCatchPattern":"try {\n  mountScrollbar(viewport);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"ResizeObserver\")) {\n    mountNativeScrollbar(viewport); // browser default scrolling\n  } else throw err;\n}","preventionTips":["Polyfill ResizeObserver at the app entry before any component mounts.","Browserlist-test the oldest webview you ship.","In jsdom tests, always stub global.ResizeObserver.","Feature-detect modern DOM APIs in component setup and degrade instead of throwing."],"tags":["svelte","browser-api","polyfill"],"backgroundTag":"missing-dependency","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}