CloakHQ/CloakBrowser · error · StealthEvaluationError

StealthEvaluationError: {selector}

Error message

StealthEvaluationError: {selector}

What it means

StealthEvaluationError mapped from an unrecognized StealthStatus (or Ok with null snapshot) in LocatorHumanizer.SnapshotAsync: the stealth-world snapshot for the selector failed in a way that isn't NotFound or Unsupported — the evaluation itself errored or returned malformed data.

Source

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

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);
    }

    private static async Task<BoundingBox?> GetBoxAsync(
        IsolatedWorld world, string selector, double timeoutMs)
    {
        double deadline = System.Environment.TickCount64 + System.Math.Max(0, timeoutMs);
        var result = await StealthDom.BoxAsync(world, selector).ConfigureAwait(false);
        while ((result.Status == StealthStatus.NotFound || result.Status == StealthStatus.EvaluationFailed)
            && System.Environment.TickCount64 < deadline)
        {

View on GitHub (pinned to d6bad5de26)

Solutions

  1. Wait for load state / network idle before the humanized action
  2. Check page.IsClosed and context validity first
  3. Retry once — transient evaluation races are common around navigation
  4. If it persists, capture the stealth world state to see whether scripts are intact

Example fix

// before
await page.Locator("#x").HumanClickAsync();

// after
await page.WaitForLoadStateAsync(LoadState.DOMContentLoaded);
await page.Locator("#x").HumanClickAsync();
Defensive patterns

Strategy: retry

Validate before calling

await page.WaitForLoadStateAsync(LoadState.DOMContentLoaded);
if (page.IsClosed) return;

Try / catch

catch (StealthEvaluationError) when (transient) { await Task.Delay(250); retry once; }

Prevention

When it happens

Trigger: The isolated-world snapshot JS throwing or returning invalid JSON during navigation, page crash, or context teardown while a humanized locator action runs.

Common situations: Races with navigation/redirects, pages under heavy load timing out script execution, or calls issued while the page is closing.

Related errors


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