{"record":{"id":"6b127b2eec8a2f81","repo":"CloakHQ/CloakBrowser","slug":"viewport-size-not-available-6b127b","errorCode":null,"errorMessage":"Viewport size not available","messagePattern":"Viewport size not available","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/CloakBrowser/Human/HumanScroll.cs","lineNumber":107,"sourceCode":"    /// overshoot behavior.\n    /// </summary>\n    /// <returns>(box, cursorX, cursorY, didScroll) - didScroll is false when the\n    /// element was already in the viewport.</returns>\n    public static async Task<ScrollResult> HumanScrollIntoViewAsync(\n        IRawScrollPage page,\n        IRawMouse raw,\n        Func<Task<BoundingBox?>> getBox,\n        double cursorX, double cursorY,\n        HumanConfig cfg)\n    {\n        var viewport = page.ViewportSize;\n        if (viewport == null)\n            // Headed launches default to no_viewport so the page tracks the real OS\n            // window; ViewportSize is then null. Fall back to the live window\n            // dimensions so humanize works headed (the stealth-relevant mode).\n            viewport = await page.GetLiveWindowSizeAsync().ConfigureAwait(false);\n        if (viewport == null || viewport.Value.Height == 0)\n            throw new InvalidOperationException(\"Viewport size not available\");\n\n        int viewportHeight = viewport.Value.Height;\n        int viewportWidth = viewport.Value.Width;\n\n        var box = await getBox().ConfigureAwait(false);\n        if (box == null)\n            throw new InvalidOperationException(\"Element not found while scrolling into view\");\n\n        if (IsInViewport(box.Value, viewportHeight, cfg))\n            return new ScrollResult(box.Value, cursorX, cursorY, false);\n\n        // Already fully visible but off-center, with the page pinned at the boundary\n        // in the needed direction: scrolling can't help, so don't waste the budget.\n        bool fullyVisible = box.Value.Y >= 0 && box.Value.Y + box.Value.Height <= viewportHeight;\n        if (fullyVisible)\n        {\n            double zoneMid = viewportHeight * (cfg.ScrollTargetZone.Min + cfg.ScrollTargetZone.Max) / 2;\n            bool needUp = box.Value.Y + box.Value.Height / 2 < zoneMid;","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/CloakHQ/CloakBrowser/blob/d6bad5de261bedf025280ace1d14e800aee13923/dotnet/src/CloakBrowser/Human/HumanScroll.cs#L89-L125","documentation":"InvalidOperationException from HumanScrollIntoViewAsync when neither page.ViewportSize nor the live window dimensions (via GetLiveWindowSizeAsync) yield a usable viewport height (null or Height == 0). Without a viewport height the scroller cannot compute zones or distances.","triggerScenarios":"Calling humanized scroll-into-view when the page has no ViewportSize (headed no_viewport mode) AND the stealth-world viewport probe also returns null or a zero-height object — e.g. navigation happening concurrently, or the stealth isolated world not being installed.","commonSituations":"Headed launches with NoViewport = true where the page is closing/closed, about:blank with no layout, race between navigation and humanize calls, or a stripped-down stealth script that doesn't expose the viewport probe.","solutions":["Ensure the page has fully navigated to real content before humanized scrolling","For headless runs, set an explicit Viewport in BrowserContextOptions so ViewportSize is populated","Check the page isn't closing (IsClosed) before issuing scroll calls","Verify the stealth scripts are installed (they provide the live-dimension fallback)"],"exampleFix":"// before\nvar ctx = await browser.NewContextAsync(); // NoViewport default in headed mode\n\n// after\nvar ctx = await browser.NewContextAsync(new BrowserContextOptions { Viewport = new(1280, 800) });","handlingStrategy":"validation","validationCode":"if (page.ViewportSize is null or { Height: 0 }) await page.SetViewportSizeAsync(1280, 800);","typeGuard":null,"tryCatchPattern":"catch (InvalidOperationException e) when (e.Message == \"Viewport size not available\") { /* set viewport, retry */ }","preventionTips":["Set explicit viewport for headless runs","Don't call scroll APIs on closing/blank pages","Wait for a real navigation before humanizing"],"tags":["humanize","scroll","viewport","configuration"],"backgroundTag":"viewport-not-available","analyzedSha":"d6bad5de261bedf025280ace1d14e800aee13923","analyzedAt":"2026-08-28T14:13:12.918Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}