Protocol error (Target.activateTarget): Session closed

Learn how to fix the 'Session closed' error when trying to interact with a closed browser session


Protocol error (Target.activateTarget): Session closed

This error occurs when you try to interact with a browser session that has been closed or disconnected. This typically happens due to premature session closure or connection issues.

Common Causes

  • Premature session closure: Browser session is closed before operations complete
  • Connection issues: Network problems causing session disconnection
  • Resource cleanup: Automatic cleanup closing sessions too early
  • Multiple session handling: Trying to use a closed session
  • Error handling issues: Session closes during error recovery

Solutions

1. Implement proper session management

let browser;
let page;

async function initializeSession() {
  browser = await puppeteer.launch({
    // Add connection options
    args: ['--no-sandbox'],
    timeout: 30000
  });
  
  page = await browser.newPage();
  return { browser, page };
}

async function cleanupSession() {
  if (page) await page.close();
  if (browser) await browser.close();
}

// Usage
try {
  const { browser, page } = await initializeSession();
  await page.goto('https://example.com');
  // ... your automation code ...
} catch (error) {
  console.error('Error:', error);
} finally {
  await cleanupSession();
}

2. Add session state checks

async function safeOperation(page, operation) {
  if (!page || !page.isConnected()) {
    throw new Error('Page session is closed or invalid');
  }
  
  try {
    await operation();
  } catch (error) {
    if (error.message.includes('Session closed')) {
      console.log('Session was closed during operation');
      // Handle the error appropriately
    }
    throw error;
  }
}

3. Implement session recovery

async function runWithSessionRecovery() {
  let browser = await puppeteer.launch();
  let page = await browser.newPage();
  
  try {
    await page.goto('https://example.com');
    // ... your automation code ...
  } catch (error) {
    if (error.message.includes('Session closed')) {
      console.log('Session was closed, attempting recovery...');
      // Clean up old session
      await browser.close();
      // Create new session
      browser = await puppeteer.launch();
      page = await browser.newPage();
      await page.goto('https://example.com');
    }
    throw error;
  }
}

4. Use session event listeners

const browser = await puppeteer.launch();

// Listen for browser disconnect
browser.on('disconnected', () => {
  console.log('Browser session was disconnected');
});

// Listen for target changes
browser.on('targetcreated', async (target) => {
  console.log('New target created:', target.url());
});

browser.on('targetdestroyed', async (target) => {
  console.log('Target destroyed:', target.url());
});

5. Implement retry logic with session checks

async function operateWithRetry(page, operation, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      if (!page.isConnected()) {
        throw new Error('Session is closed');
      }
      await operation();
      return;
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      console.log(`Retry ${i + 1} of ${maxRetries}`);
      // Wait before retrying
      await new Promise(resolve => setTimeout(resolve, 1000));
    }
  }
}

Still Encountering Issues?

If you’re still having trouble with session closure errors, you can use a visual testing tool like Buglesstack to debug your automation and track session lifecycle events.

try {
	await page.goto('https://www.google.com/search?q=puppeteer');		
	await page.waitForSelector('[name="q"]');
}
catch (error) {
	// Prepare buglesstack data
	const buglesstackData = {
		url: page.url(),
		screenshot: await page.screenshot({ encoding: 'base64' }),
		html: await page.content(),
		metadata: {},
		message: error.message,
		stack: error.stack
	};

	// Get your access token from https://app.buglesstack.com
	const ACCESS_TOKEN = 'HERE_YOUR_ACCESS_TOKEN';

	// Send error to buglesstack
	await axios.post('https://app.buglesstack.com/api/v1/crashes', buglesstackData, {
		headers: {
			Authorization: `Bearer ${ACCESS_TOKEN}`,
			'Content-Type': 'application/json'
		}
	});
		
	// Re-throw the error to propagate it
	throw error;
}

By implementing proper session management and error handling, you can resolve the “Session closed” error and make your automation more robust.

Save days debugging
pptr crashes

Speed up production debugging with instant visualisations of your puppeteer crashes.