Skip to content

fix: prevent DevToolsServer port conflicts on BrowserPool relaunch#212

Merged
nikitachapovskii-dev merged 3 commits intomasterfrom
fix/devtools-server-eaddrinuse
Feb 3, 2026
Merged

fix: prevent DevToolsServer port conflicts on BrowserPool relaunch#212
nikitachapovskii-dev merged 3 commits intomasterfrom
fix/devtools-server-eaddrinuse

Conversation

@nikitachapovskii-dev
Copy link
Contributor

Fixes a Web Scraper dev-mode issue where DevToolsServer was started from BrowserPool’s preLaunchHook on every browser launch/relaunch, causing EADDRINUSE port conflicts after browser/page crashes or pool relaunches. The PR makes DevToolsServer startup idempotent by starting it only once per actor process (reusing a cached start promise on subsequent hook calls) and registers a single Actor.on('exit') cleanup to stop the server.

Closes #208

@nicklamonov nicklamonov requested a review from ruocco-l January 29, 2026 12:23
@nicklamonov
Copy link
Contributor

It's interesting why this moved to Backlog... (

@nikitachapovskii-dev nikitachapovskii-dev self-assigned this Jan 29, 2026
Copy link
Member

@barjin barjin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @nikitachapovskii-dev !

I only have a few points, mostly regarding the naming:

Comment on lines +253 to +258
if (!this._devToolsExitHookRegistered) {
this._devToolsExitHookRegistered = true;
Actor.on('exit', () => {
this._devToolsServer?.stop?.();
});
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this guard (_devToolsExitHookRegistered) is imo not necessary, as this IIFE (L236 and below) will only run exactly once, no?

Copy link
Contributor Author

@nikitachapovskii-dev nikitachapovskii-dev Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, for our current case it isn’t necessary. It's just an extra safety guard to prevent accidentally registering multiple Actor.on('exit') listeners if (whatever?) causes rerunning the startup block. Assuming that IIFE always runs only once we can remove this

private static _devToolsServer: any | null = null;
private static _devToolsExitHookRegistered = false;

private static async _startDevToolsServerOnce(): Promise<void> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private static async _startDevToolsServerOnce(): Promise<void> {
private static async startDevToolsServerOnce(): Promise<void> {

private is enough, eslint is right :) We try not to do underscores in our new TS code (there are some legacy exceptions).

chromeRemoteDebuggingPort: CHROME_DEBUGGER_PORT,
});

await this._devToolsServer.start();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this._devToolsServer doesn't have to be a static variable, we do not refer to it anywhere else.

What if _startDevToolsServerOnce (maybe renamed to sth like getDevToolsServer()) returned Promise<Server> instead, so the caller can do as they see fit - wdyt?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, we don't need that as a static.
Return of the started server instance seems good for me.

@@ -1,5 +1,15 @@
import { launchPuppeteer } from '@crawlee/puppeteer';
import type { Browser, Page } from 'puppeteer';
import {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this test file was made to test the bundle.browser.ts file (see the name). Please update the name or create a new test file.

Copy link
Member

@barjin barjin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, thank you!

@nikitachapovskii-dev nikitachapovskii-dev merged commit 27259c3 into master Feb 3, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Double initialization of DevToolsServer leads to error in web-scraper

3 participants