Stopping Stuck Browser Actions with CDP
I’ve spent many hours debugging automation scripts that just… stop. You send a command to evaluate some JavaScript, it takes longer than expected, and suddenly your entire browser tab is unresponsive. Every click or type action you send afterward gets stuck in a queue.
It’s a common pain point when your execution engine serializes every command. If one script hangs, the whole tab hangs. I want to show you how we are moving act:evaluate to a separate CDP-based engine to keep your browser operations moving.
What You’ll Need
Section titled “What You’ll Need”browser.evaluateEnabledgate must be active.- Access to the browser-level CDP socket.
Quick Start
Section titled “Quick Start”The new architecture ensures that a stuck evaluate command cannot block later actions on the same tab. Here is how the path works now.
- Set a Budget: We use a single budget for the entire request. The
createBudgethelper links your timeout and abort signals.
// The budget helper provides a single source of truthconst budget = createBudget({ timeoutMs, signal });
// It exposes these properties:// budget.signal (the linked AbortSignal)// budget.deadlineAtMs (absolute deadline)// budget.remainingMs() (budget for child operations)-
Isolate the Execution: The system connects to the CDP endpoint and uses
Target.attachToTargetwithflatten: trueto get asessionId. This bypasses the standard Playwright command queue. -
Target Elements with Refs: If you provide a
ref, the system looks for abackendDOMNodeId. This allows us to run element-level evaluations without switching everything off Playwright.
{ "role": "button", "name": "Submit", "nth": 0, "backendDOMNodeId": 12345}- Run the Script: The engine executes
Runtime.evaluatefor page-level scripts orRuntime.callFunctionOnfor elements. If the script times out, the system sendsRuntime.terminateExecutionand closes the session.
Troubleshooting
Section titled “Troubleshooting”- Script Side Effects: When a timeout or abort occurs, we trigger
Runtime.terminateExecution. While this unblocks the queue, it can leave the page in an inconsistent state because the JavaScript was forcibly stopped. - Mapping Failures: If the AX tree cannot map a
refto abackendDOMNodeId, the system falls back to the standard Playwright path. This ensures the action still attempts to run, even if it uses the older, serialized queue.
If you have more questions about setting this up, check out the AI Setup Assistant.
What’s Next
Section titled “What’s Next”OpenClaw Expert
Still stuck?
If this page didn't answer your case, ask OpenClaw Expert for step-by-step guidance.