Skip to content

Conversation

@rise-erpelding
Copy link
Contributor

@rise-erpelding rise-erpelding commented Dec 19, 2025

Fix Content Script Communication Error

BLDL-31

Summary

Refactored the background script's message handling architecture to eliminate the "Could not establish connection. Receiving end does not exist" error and improve code clarity.

image image

Problem

The previous implementation had several architectural issues:

  1. Used error handling for normal flow: Every first click on a page would throw and catch an error, treating the expected case (content script not loaded) as an exceptional case.

  2. Insufficient retry logic: After injecting the content script, the code waited only 150ms before attempting to send a message. This was not enough time for the dynamic import() in content.js to complete and set up the message listener, causing a "Receiving end does not exist" error.

  3. Misleading error logging: The code logged errors for normal operation (content script injection), making it difficult to distinguish real failures from expected behavior.

  4. No happy path: There was no clear success path - the code always relied on try/catch blocks even for normal operation.

Solution

Refactored the message handling to use explicit checks and retry logic:

  1. Explicit content script detection: Added isContentScriptLoaded() function that returns a boolean instead of throwing an error.

  2. Clear conditional logic: Replaced try/catch-based flow control with an explicit if/else that handles both cases as normal operations:

    • If content script is loaded → send message directly (happy path)
    • If content script is not loaded → inject it, then retry sending message (also a valid path)
  3. Exponential backoff retry: Implemented sendMessageWithRetry() that waits progressively longer (100ms, 200ms, 300ms, etc.) until the content script's message listener is ready, with a maximum of 10 attempts.

  4. Better error reporting: Errors are now only logged when all retry attempts are exhausted, indicating a genuine failure.

Changes

background.js

  • Added isContentScriptLoaded(tabId): Checks if content script is loaded by attempting to send a ping message
  • Added sendMessageWithRetry(tabId, message, maxRetries): Sends message with exponential backoff retries
  • Refactored handleIconClick(): Uses explicit conditional logic instead of try/catch for flow control

Validation Instructions

Setup

  1. Build the extension: npm run build (or your build command)
  2. Load the unpacked extension in your browser:
    • Chrome: Navigate to chrome://extensions/, enable "Developer mode", click "Load unpacked"
    • Firefox: Navigate to about:debugging#/runtime/this-firefox, click "Load Temporary Add-on"

Test Cases

Test 1: First Click on a Page (Content Script Not Loaded)

  1. Navigate to any HTTP/HTTPS webpage (e.g., https://example.com)
  2. Click the extension icon
  3. Expected:
    • Panel appears after a brief delay (typically 100-500ms)
    • No errors in browser console or extension background page console
    • No "Could not establish connection" errors

Test 2: Second Click on Same Page (Content Script Already Loaded)

  1. With the panel visible from Test 1, click the extension icon again
  2. Expected:
    • Panel disappears immediately (no delay)
    • No errors in console

Test 3: Toggle Multiple Times

  1. Click the extension icon 5-10 times rapidly
  2. Expected:
    • Panel toggles on/off smoothly
    • No errors accumulate in console

Test 4: Multiple Tabs

  1. Open 3 different tabs with HTTP/HTTPS pages
  2. Click the extension icon in each tab (first click per tab)
  3. Expected:
    • Each tab's first click shows panel after brief delay
    • Subsequent clicks in each tab respond immediately
    • No errors in any console

Test 5: Background Page Console Check

  1. Navigate to chrome://extensions/ (or about:debugging in Firefox)
  2. Find your extension and click "Inspect views: background page" (or "Inspect")
  3. Navigate to any webpage and click the extension icon
  4. Expected:
    • No error messages in the background page console
    • If any messages appear, they should only be for genuine failures, not normal operation

What NOT to See

  • ❌ "Error in handleIconClick: Could not establish connection. Receiving end does not exist"
  • ❌ Any errors during normal icon clicks
  • ❌ Panel failing to appear on first click

What TO See

  • ✅ Panel appears on every click (might take 100-500ms on first click per page)
  • ✅ Panel toggles instantly on subsequent clicks
  • ✅ Clean console with no errors during normal operation
  • ✅ Only see errors if retries are genuinely exhausted (would require blocking the content script from loading)

@rise-erpelding rise-erpelding self-assigned this Dec 19, 2025
@github-actions
Copy link

📦 Extension packages built successfully!

Download your Chrome and Firefox extension packages

@rise-erpelding rise-erpelding marked this pull request as ready for review January 13, 2026 18:15
@jonoliver jonoliver self-requested a review January 13, 2026 18:19
Copy link
Member

@jonoliver jonoliver left a comment

Choose a reason for hiding this comment

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

Thanks Rise! I verified that we no longer see the Could not establish connection errors in Chrome or Firefox, and that that we see the Failed to communicate with content script error if the max retries are exceeded.


} catch (error) {
// If message fails, content.js isn't loaded. Inject it, and execute the content script
} else {
Copy link
Member

Choose a reason for hiding this comment

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

We may ultimately want to do some error handling around the sendMessage call above and loading the content script below, but that can be another PR.

@rise-erpelding rise-erpelding merged commit cee8aa8 into main Jan 13, 2026
1 check 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.

3 participants