{"record":{"id":"50ba91b264cf182d","repo":"CloakHQ/CloakBrowser","slug":"element-lost-after-scrolling-into-view-50ba91","errorCode":null,"errorMessage":"Element lost after scrolling into view","messagePattern":"Element lost after scrolling into view","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/CloakBrowser/Human/HumanScroll.cs","lineNumber":210,"sourceCode":"        {\n            int overshootPx = (int)(Math.Round(HumanRandom.RandRange(cfg.ScrollOvershootPx)) * direction);\n            await SmoothWheelAsync(raw, overshootPx, cfg).ConfigureAwait(false);\n            await HumanRandom.SleepMsAsync(HumanRandom.RandRange(cfg.ScrollSettleDelay)).ConfigureAwait(false);\n            int corrections = HumanRandom.RandIntRange((1, 2));\n            for (int c = 0; c < corrections; c++)\n            {\n                int corrDelta = (int)(Math.Round(HumanRandom.Rand(40, 80)) * -direction);\n                await SmoothWheelAsync(raw, corrDelta, cfg).ConfigureAwait(false);\n                await HumanRandom.SleepMsAsync(HumanRandom.Rand(100, 250)).ConfigureAwait(false);\n            }\n        }\n\n        // Settle.\n        await HumanRandom.SleepMsAsync(HumanRandom.RandRange(cfg.ScrollSettleDelay)).ConfigureAwait(false);\n\n        box = await getBox().ConfigureAwait(false);\n        if (box == null)\n            throw new InvalidOperationException(\"Element lost after scrolling into view\");\n\n        return new ScrollResult(box.Value, cursorX, cursorY, true);\n    }\n}\n","sourceCodeStart":192,"sourceCodeEnd":215,"githubUrl":"https://github.com/CloakHQ/CloakBrowser/blob/d6bad5de261bedf025280ace1d14e800aee13923/dotnet/src/CloakBrowser/Human/HumanScroll.cs#L192-L215","documentation":"InvalidOperationException thrown at the end of HumanScrollIntoViewAsync: after performing the humanized scroll and settle delay, re-querying the element's box returns null. The element disappeared from the DOM during the scroll.","triggerScenarios":"Scrolling to an element that gets removed/re-rendered as a side effect of scrolling — lazy loaders that replace nodes, infinite lists that recycle DOM nodes, or SPAs that re-mount components on scroll events.","commonSituations":"Virtualized/infinite-scroll lists, content lazy-loaded on scroll that swaps the target node, or the page navigating away mid-scroll.","solutions":["Use a stable selector that survives re-renders (data-testid rather than index-based nth-child)","Re-locate the element and retry the scroll after the lazy content settles","Wait for DOM stability after scroll-triggering loads before asserting on the element","If the node is intentionally replaced, target the container and scroll to that instead"],"exampleFix":"// before\nawait page.HumanScrollIntoViewAsync(\"ul > li:nth-child(900)\");\n\n// after\nawait page.HumanScrollIntoViewAsync(\"ul[data-testid='results']\");\nawait page.WaitForSelectorAsync(\"ul > li:nth-child(900)\");","handlingStrategy":"retry","validationCode":"// cannot fully validate; ensure stable selector exists\nvar count = await page.Locator(selector).CountAsync(); // use resilient selector","typeGuard":null,"tryCatchPattern":"catch (InvalidOperationException e) when (e.Message.Contains(\"lost after scrolling\")) { re-locate by stable selector and retry once }","preventionTips":["Prefer container/data-testid selectors over positional ones","Wait for DOM stability after scroll-triggered lazy loads","Avoid scroll calls during navigation"],"tags":["humanize","scroll","dom-mutation","race-condition"],"backgroundTag":"stale-element-reference","analyzedSha":"d6bad5de261bedf025280ace1d14e800aee13923","analyzedAt":"2026-08-28T14:13:12.918Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}