Skip to content
Agent Orchestration
Skill

/browser-edge-cases

SOP for debugging browser automation failures on complex websites. Use when browser tools fail on specific sites like LinkedIn, Twitter/X, SPAs, or sites with Shadow DOM.

From plugin
aden-hive-hive
11k4 skills5 agents1 MCP
Install
$ npx -y skills add aden-hive/hive --skill browser-edge-cases --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/browser-edge-cases

Context preview

The summary Claude sees to decide when to auto-load this skill.

SOP for debugging browser automation failures on complex websites. Use when browser tools fail on specific sites like LinkedIn, Twitter/X, SPAs, or sites with Shadow DOM.

SKILL.md

browser-edge-cases.SKILL.md
name: browser-edge-cases
description: SOP for debugging browser automation failures on complex websites. Use when browser tools fail on specific sites like LinkedIn, Twitter/X, SPAs, or sites with Shadow DOM.
license: MIT

Browser Tool Edge Cases

Standard Operating Procedure for debugging and fixing browser automation failures on complex websites.

When to Use This Skill

  • `browser_interact(action="scroll")` succeeds but page doesn't move
  • `browser_interact(action="left_click")` succeeds but no action triggered
  • `browser_interact(action="type")` text disappears or doesn't work
  • `browser_snapshot` hangs or returns stale content
  • `browser_navigate` loads wrong content

SOP: Debugging Browser Tool Failures

Phase 1: Reproduce & Isolate

1. Create minimal test case demonstrating failure
2. Test against simple site (example.com) to verify tool works
3. Test against problematic site to confirm issue

**Quick isolation test:**

# Test 1: Does the tool work at all?
await browser_navigate(tab_id, "https://example.com")
result = await browser_interact(action="scroll", tab_id=tab_id, scroll_direction="down", scroll_amount=100)
# Should work on simple sites

# Test 2: Does it fail on the problematic site?
await browser_navigate(tab_id, "https://linkedin.com/feed")
result = await browser_interact(action="scroll", tab_id=tab_id, scroll_direction="down", scroll_amount=100)
# If this fails but example.com works → site-specific edge case

Phase 2: Analyze Root Cause

**Step 2a: Check console for errors**

console = await browser_console(tab_id)
# Look for: CSP violations, React errors, JavaScript exceptions

**Step 2b: Inspect DOM structure**

html = await browser_html(tab_id)
snapshot = await browser_snapshot(tab_id)
# Look for:
# - Nested scrollable divs (overflow: scroll/auto)
# - Shadow DOM roots
# - iframes
# - Custom widgets

**Step 2c: Identify the pattern**

| Symptom | Likely Cause | Check | |---------|--------------|-------| | Scroll doesn't move | Nested scroll container | Look for `overflow: scroll` divs | | Click no effect | Element covered | Check `getBoundingClientRect` vs viewport | | Type clears | Autocomplete/React | Check for event listeners on input; try a `type` action with no selector | | Snapshot hangs | Huge DOM | Check node count in snapshot | | Snapshot stale | SPA hydration | Wait after navigation |

Phase 3: Implement Multi-Layer Fix

**Pattern: Always have fallbacks**

async def robust_operation(tab_id):
    # Method 1: Primary approach
    try:
        result = await primary_method(tab_id)
        if verify_success(result):
            return result
    except Exception:
        pass

    # Method 2: CDP fallback
    try:
        result = await cdp_fallback(tab_id)
        if verify_success(result):
            return result
    except Exception:
        pass

    # Method 3: JavaScript fallback
    return await javascript_fallback(tab_id)

**Pattern: Always add timeouts**

# Bad - can hang forever
result = await browser_snapshot(tab_id)

# Good - fails fast with useful error
try:
    result = await browser_snapshot(tab_id, timeout_s=10.0)
except asyncio.TimeoutError:
    # Handle timeout gracefully
    result = await fallback_snapshot(tab_id)

Phase 4: Verify Fix

1. Run against problematic site → should work
2. Run against simple site → should still work (regression check)
3. Document in registry.md

Pattern Library

P1: Nested Scrollable Containers

**Sites:** LinkedIn, Twitter/X, any SPA with scrollable feeds

**Detection:**

// Find largest scrollable container
const candidates = [];
document.querySelectorAll('*').forEach(el => {
    const style = getComputedStyle(el);
    if (style.overflow.includes('scroll') || style.overflow.includes('auto')) {
        const rect = el.getBoundingClientRect();
        if (rect.width > 100 && rect.height > 100) {
            candidates.push({el, area: rect.width * rect.height});
        }
    }
});
candidates.sort((a, b) => b.area - a.area);
return candidates[0]?.el;

**Fix:** Dispatch scroll events at container's center, not viewport center.

P2: Element Covered by Overlay

**Sites:** Modals, tooltips, SPAs with loading overlays

**Detection:**

const rect = element.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
const topElement = document.elementFromPoint(centerX, centerY);
return topElement === element || element.contains(topElement);

**Fix:** Wait for overlay to disappear, or use JavaScript click.

P3: React Synthetic Events

**Sites:** React SPAs, modern web apps

**Detection:** If CDP click doesn't trigger handler but manual click works.

**Fix:** Use JavaScript click as primary:

element.click();

P4: Huge DOM / Accessibility Tree

**Sites:** LinkedIn, Facebook, Twitter (feeds with 1000s of nodes)

**Detection:**

document.querySelectorAll('*').length > 5000

**Fix:** 1. Add timeout to snapshot operation 2. Truncate tree at 2000 nodes 3. Fall back to DOM-based snapshot if accessibility tree too large

P5: SPA Hydration Delay

**Sites:** React, Vue, Angular SPAs after navigation

**Detection:**

// Check if React app has hydrated
document.querySelector('[data-reactroot]') ||
document.querySelector('[data-reactid]')

**Fix:** Wait for specific selector after navigation:

await browser_navigate(tab_id, url, wait_until="load")
await browser_interact(action="wait", tab_id=tab_id, wait_for_selector='[data-testid="content"]', timeout_ms=5000)

P6: Shadow DOM

**Sites:** Components using Shadow DOM, Lit elements

**Detection:**

document.querySelectorAll('*').some(el => el.shadowRoot)

**Fix:** Pierce shadow root:

function queryShadow(selector) {
    const parts = selector.split('>>>');
    let node
Read more
Ships withaden-hive-hive

Multi-Agent Harness for Production AI

Get the whole plugin

Other skills on aden-hive-hive.