CloakHQ/CloakBrowser · critical · StealthWorldUnavailableError

StealthWorldUnavailableError

Error message

StealthWorldUnavailableError

What it means

StealthWorldUnavailableError thrown by LocatorHumanizer.WorldAsync when cursor.GetStealthAsync() returns null — the locator humanizer needs the stealth isolated world to run its DOM scripts, and it isn't present on this page/context.

Source

Thrown at dotnet/src/CloakBrowser/Wrappers/LocatorHumanizer.cs:12

using CloakBrowser.Human;
using Microsoft.Playwright;

namespace CloakBrowser.Wrappers;

/// <summary>Humanized locator actions. Direct page.Locator selectors use the canonical isolated DOM world; unknown locator shapes retain the legacy Playwright path.</summary>
internal static class LocatorHumanizer
{
    private static double RemainingMs(double deadline) => Actionability.RemainingMs(deadline);

    private static async Task<IsolatedWorld> WorldAsync(HumanCursor cursor) =>
        await cursor.GetStealthAsync().ConfigureAwait(false) ?? throw new StealthWorldUnavailableError();

    internal static async Task<StealthSnapshot> SnapshotAsync(HumanCursor cursor, string selector)
    {
        var (status, snapshot) = await StealthDom.SnapshotAsync(await WorldAsync(cursor).ConfigureAwait(false), selector).ConfigureAwait(false);
        return status switch
        {
            StealthStatus.Ok when snapshot != null => snapshot.Value,
            StealthStatus.NotFound => throw new ElementNotAttachedError(selector),
            StealthStatus.Unsupported => throw new UnsupportedHumanizeSelectorError(selector),
            _ => throw new StealthEvaluationError(selector),
        };
    }

    internal static async Task EnsureActionableAsync(HumanCursor cursor, string selector,
        IReadOnlySet<string> checks, double timeout, bool force)
    {
        var world = await WorldAsync(cursor).ConfigureAwait(false);
        await Actionability.EnsureActionableAsync(cursor.Page, selector, checks, timeout, force, world).ConfigureAwait(false);

View on GitHub (pinned to d6bad5de26)

Solutions

  1. Create contexts/pages through CloakBrowser's launch/launch_context helpers so the stealth world is installed
  2. Don't disable the stealth/isolated-world feature for pages you humanize
  3. Guard calls with a page-open check and stop humanizing during teardown

Example fix

# before
context = await browser.new_context()  # no stealth world

# after
context = await cloakbrowser.launch_context(...)  # installs stealth world
Defensive patterns

Strategy: validation

Validate before calling

var world = await cursor.GetStealthAsync();
if (world == null) throw new InvalidOperationException("create context via cloakbrowser launch APIs");

Try / catch

catch (StealthWorldUnavailableError) { recreate context through launch_context; }

Prevention

When it happens

Trigger: Calling humanized locator actions (Check/Uncheck/Click via humanize wrappers) on a page whose context was created without stealth scripts, or after the world has been torn down (page closing).

Common situations: Creating a BrowserContext manually instead of via CloakBrowser's launch APIs, disabling stealth features programmatically, or racing page teardown.

Related errors


AI-assisted analysis of CloakHQ/CloakBrowser@d6bad5de26 (2026-08-28). Data as JSON: /api/errors/4cbc90cb84c171cf. Report an issue: GitHub.