CloakHQ/CloakBrowser · error · ElementNotAttachedError

ElementNotAttachedError: {sourceSelector}

Error message

ElementNotAttachedError: {sourceSelector}

What it means

Thrown by the humanized drag-and-drop flow in HumanPage when the SOURCE element's bounding box cannot be resolved within the timeout. It means GetBoxAsync returned null for the source selector, so the drag cannot compute a start point.

Source

Thrown at dotnet/src/CloakBrowser/Human/HumanPage.cs:636

        return scroll.DidScroll;
    }

    // -----------------------------------------------------------------------
    // Drag-and-drop (humanized: move to source center, down, move to target, up)
    // -----------------------------------------------------------------------

    /// <summary>Human-like drag from <paramref name="sourceSelector"/> to
    /// <paramref name="targetSelector"/>. Port of <c>_frame_drag_and_drop</c> / <c>_humanized_drag_to</c>:
    /// moves to the source center, presses, moves to the target center, releases.</summary>
    public async Task DragAndDropAsync(string sourceSelector, string targetSelector, HumanActionOptions? options = null)
    {
        await EnsureCursorInitAsync().ConfigureAwait(false);
        double timeout = options?.Timeout ?? 30000;

        var srcBox = await GetBoxAsync(sourceSelector, timeout).ConfigureAwait(false);
        var tgtBox = await GetBoxAsync(targetSelector, timeout).ConfigureAwait(false);
        if (srcBox == null)
            throw new ElementNotAttachedError(sourceSelector);
        if (tgtBox == null)
            throw new ElementNotAttachedError(targetSelector);

        BoundingBox src = srcBox.Value;
        BoundingBox tgt = tgtBox.Value;
        double sx = src.X + src.Width / 2;
        double sy = src.Y + src.Height / 2;
        double tx = tgt.X + tgt.Width / 2;
        double ty = tgt.Y + tgt.Height / 2;

        await HumanMouse.HumanMoveAsync(_rawMouse, _cursor.X, _cursor.Y, sx, sy, _cfg).ConfigureAwait(false);
        _cursor.X = sx; _cursor.Y = sy;
        await HumanRandom.SleepMsAsync(HumanRandom.Rand(100, 200)).ConfigureAwait(false);
        await _rawMouse.DownAsync().ConfigureAwait(false);
        await HumanRandom.SleepMsAsync(HumanRandom.Rand(80, 150)).ConfigureAwait(false);
        await HumanMouse.HumanMoveAsync(_rawMouse, _cursor.X, _cursor.Y, tx, ty, _cfg).ConfigureAwait(false);
        _cursor.X = tx; _cursor.Y = ty;
        await HumanRandom.SleepMsAsync(HumanRandom.Rand(80, 150)).ConfigureAwait(false);

View on GitHub (pinned to d6bad5de26)

Solutions

  1. Verify the source selector matches exactly one attached element (test with page.QuerySelectorAsync first or a Playwright locator)
  2. Wait for the element to be visible before dragging (page.WaitForSelectorAsync with state Visible)
  3. Increase options.Timeout
  4. If the element is in a frame/shadow DOM, use a selector scoped to that context

Example fix

// before
await page.DragAsync("#src", "#dst");

// after
await page.WaitForSelectorAsync("#src", new() { State = WaitForSelectorState.Visible });
await page.DragAsync("#src", "#dst", new DragOptions { Timeout = 60000 });
Defensive patterns

Strategy: validation

Validate before calling

var el = await page.QuerySelectorAsync(sourceSelector);
if (el == null) throw new InvalidOperationException($"source missing: {sourceSelector}");

Try / catch

catch (ElementNotAttachedError e) when (e.Message.Contains(sourceSelector)) { /* re-wait and retry once */ }

Prevention

When it happens

Trigger: Calling HumanPage drag APIs (e.g. DragAsync(sourceSelector, targetSelector, options)) where the source selector matches no attached element within options.Timeout (default 30000 ms), or the element is detached/hidden when the box is queried.

Common situations: Selector typo, element rendered late (SPA), element inside an iframe or shadow root the selector doesn't reach, or a too-short options.Timeout passed by the caller.

Related errors


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