{"record":{"id":"1165ef7bf1c19842","repo":"CloakHQ/CloakBrowser","slug":"viewport","errorCode":null,"errorMessage":"<viewport>","messagePattern":"<viewport>","errorType":"exception","errorClass":"StealthEvaluationError","httpStatus":null,"severity":"error","filePath":"dotnet/src/CloakBrowser/Human/PlaywrightAdapters.cs","lineNumber":102,"sourceCode":"    }\n\n    public (int Width, int Height)? ViewportSize\n    {\n        get\n        {\n            var vs = _page.ViewportSize;\n            return vs == null ? null : (vs.Width, vs.Height);\n        }\n    }\n\n    public async Task<(int Width, int Height)?> GetLiveWindowSizeAsync()\n    {\n        var world = await _getStealthAsync().ConfigureAwait(false);\n        var value = await world.EvaluateAsync(StealthDom.ViewportJs).ConfigureAwait(false);\n        if (value == null || value.Value.ValueKind != System.Text.Json.JsonValueKind.Object\n            || !value.Value.TryGetProperty(\"width\", out var width)\n            || !value.Value.TryGetProperty(\"height\", out var height))\n            throw new StealthEvaluationError(\"<viewport>\");\n\n        int resolvedWidth = (int)width.GetDouble();\n        int resolvedHeight = (int)height.GetDouble();\n        if (resolvedWidth <= 0 || resolvedHeight <= 0)\n            throw new StealthEvaluationError(\"<viewport>\");\n        return (resolvedWidth, resolvedHeight);\n    }\n\n    public async Task<(double Y, double MaxY)?> GetScrollStateAsync()\n    {\n        var world = await _getStealthAsync().ConfigureAwait(false);\n        var value = await world.EvaluateAsync(\n            \"(() => { const e = document.scrollingElement || document.documentElement;\" +\n            \" return { y: window.scrollY, maxY: Math.max(0, e.scrollHeight - e.clientHeight) }; })()\")\n            .ConfigureAwait(false);\n        if (value == null || value.Value.ValueKind != System.Text.Json.JsonValueKind.Object\n            || !value.Value.TryGetProperty(\"y\", out var y)\n            || !value.Value.TryGetProperty(\"maxY\", out var maxY))","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/CloakHQ/CloakBrowser/blob/d6bad5de261bedf025280ace1d14e800aee13923/dotnet/src/CloakBrowser/Human/PlaywrightAdapters.cs#L84-L120","documentation":"StealthEvaluationError thrown by GetLiveWindowSizeAsync when evaluating the stealth viewport JS in the isolated world fails to return an object with width/height properties — i.e. the probe result is null, not JSON, or malformed.","triggerScenarios":"Calling APIs that need live window size (scroll-into-view fallback in headed no_viewport mode) when the stealth world's EvaluateAsync returns null or a non-object — page mid-navigation, page crashed, or stealth scripts not injected.","commonSituations":"Calling humanize APIs right after GoToAsync before load completes, on a crashed page, or when the isolated world/stealth scripts were not installed (custom context setup bypassing CloakBrowser defaults).","solutions":["Await page.WaitForLoadStateAsync (DOMContentLoaded/NetworkIdle) before humanize calls","Check page.IsClosed and that the stealth world is available before calling","Let CloakBrowser create the context so stealth scripts are guaranteed installed","Retry once after a short delay if a navigation race is suspected"],"exampleFix":"// before\nawait page.GoToAsync(url);\nawait page.HumanScrollIntoViewAsync(sel);\n\n// after\nawait page.GoToAsync(url);\nawait page.WaitForLoadStateAsync(LoadState.DOMContentLoaded);\nawait page.HumanScrollIntoViewAsync(sel);","handlingStrategy":"retry","validationCode":"await page.WaitForLoadStateAsync(LoadState.DOMContentLoaded);\nif (page.IsClosed) return;","typeGuard":null,"tryCatchPattern":"catch (StealthEvaluationError e) when (e.Message == \"<viewport>\") { await Task.Delay(250); retry once; }","preventionTips":["Set explicit viewport to avoid the live-dimension fallback path","Never call humanize APIs mid-navigation","Create contexts via CloakBrowser so the stealth world exists"],"tags":["stealth","viewport","evaluation","race-condition"],"backgroundTag":"js-evaluation-failed","analyzedSha":"d6bad5de261bedf025280ace1d14e800aee13923","analyzedAt":"2026-08-28T14:13:12.918Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}