Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Duplicate execution of background.js script - Help please

240 views
Skip to first unread message

Justice Chinedu

unread,
Mar 7, 2025, 9:18:35 AMMar 7
to Chromium Extensions
Hi guys, I 'm experiencing a bug that makes my background script execute twice resulting in the duplication of functions on my script. I'm using Next Js 15 to build so I used webpack to compile my /extension files to /extension-dist which I loaded into my local chrome extension.

I've crosschecked my manifest.js and webpack but everything seems alright

I've attached screenshots of the logged output. Please, any help with this would be much appreciated.google promptfast bug.png

woxxom

unread,
Mar 7, 2025, 2:33:44 PMMar 7
to Chromium Extensions, Justice Chinedu
Without seeing the actual code I guess your code incorrectly registers the listeners twice or the message is sent twice e.g. when the content script is injected twice or when it runs in iframes.

Justice Chinedu

unread,
Mar 7, 2025, 3:59:41 PMMar 7
to Chromium Extensions, woxxom, Justice Chinedu
Thanks for answering. here are some code blocks and screenshots. Please let me know if there's any specific file you'd want to see. Thanks

user page file(prompts.js):

document.addEventListener('DOMContentLoaded', async () => {
  try {
    // Create loading indicator
    createLoadingIndicator();
   
    // Initialize Firebase auth in background
    await initAuth();

       
    // Check for Google redirect results
    checkForGoogleRedirectResult();
   
    // Check auth status and update UI
    await checkAuthStatus();
   
    // Set up event listeners
    if (authClose) {
      authClose.addEventListener('click', hideAuthModal);
    }
   
    if (signInTab) {
      signInTab.addEventListener('click', showSignInForm);
    }
   
    if (signUpTab) {
      signUpTab.addEventListener('click', showSignUpForm);
    }
   
    if (signInForm) {
      signInForm.addEventListener('submit', (e) => {
        e.preventDefault();
        const email = signInForm.querySelector('#signInEmail').value;
        const password = signInForm.querySelector('#signInPassword').value;
        emailSignIn(email, password);
      });
    }
   
    if (signUpForm) {
      signUpForm.addEventListener('submit', (e) => {
        e.preventDefault();
        const displayName = signUpForm.querySelector('#displayName').value;
        const email = signUpForm.querySelector('#signUpEmail').value;
        const password = signUpForm.querySelector('#signUpPassword').value;
        emailSignUp(displayName, email, password);
      });
    }
   
    if (googleSignInBtn) {
      googleSignInBtn.addEventListener('click', googleSignIn);
    }
   
    if (googleSignUpBtn) {
      googleSignUpBtn.addEventListener('click', googleSignIn);
    }
   
    if (tryDemoBtn) {
      tryDemoBtn.addEventListener('click', handleDemoMode);
    }
   
    // Listen for auth state changes for UI updates
    chrome.runtime.onMessage.addListener((message) => {
      if (message.action === 'authStateChanged') {
        checkAuthStatus();
      }
    });
   
  } catch (error) {
    console.error("Error initializing welcome page:", error);
    showError("Failed to initialize application. Please refresh and try again.");
  }
});


//another UI page(popup.js)
document.addEventListener('DOMContentLoaded', () => {
  initializeTemplates();
  setupEventListeners();
});




document.addEventListener('DOMContentLoaded', () => {
    userInput.focus();
    checkAuthentication();
   
    // Add CSS for history modal and loader
   
   
    // Listen for auth state changes
    chrome.runtime.onMessage.addListener((message) => {
      if (message.action === 'authStateChanged') {
        isAuthenticated = message.isAuthenticated;
       
        // Clear history list
        if (historyList) {
          historyList.innerHTML = '';
        }
       
        // Reset pagination
        historyPagination = {
          lastVisible: null,
          hasMore: true,
          isLoading: false
        };
       
        // Load history if authenticated
        if (isAuthenticated) {
          loadHistory();
        } else {
          // Show login prompt
          checkAuthentication();
        }
      }
    });
  });
})(); //BACKGROUND.JS
// Main message handler
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  console.log("Background received message:", request);

  const handleError = (error) => {
    console.error(`Error in ${request.action}:`, error);
    return {
      success: false,
      error: error.message,
      errorCode: error.code || 'UNKNOWN_ERROR'
    };
  };

  if (request.action === 'savePrompt') {
    (async () => {
      try {
        const result = await saveUserPrompt(request.data);
        sendResponse(result);
      } catch (error) {
        sendResponse({
          success: false,
          error: error.message,
          errorCode: 'SAVE_PROMPT_ERROR'
        });
      }
    })();
    return true; // keep the message channel open for async
  }

  // Handle fetchPrompts
  if (request.action === 'fetchPrompts') {
    (async () => {
      try {
        const result = await fetchPrompts(request);
        sendResponse(result);
      } catch (error) {
        sendResponse({ success: false, error: error.message });
      }
    })();
    return true;
  }

});

woxxom

unread,
Mar 7, 2025, 4:15:22 PMMar 7
to Chromium Extensions, Justice Chinedu, woxxom
1. There's no sendMessage in the code you've shown. 
2. Where's the code that prints "instance" in console.log?

Justice Chinedu

unread,
Mar 7, 2025, 8:59:04 PMMar 7
to Chromium Extensions, woxxom, Justice Chinedu
You're right.

here's the code that prints it. It's a block that I wrote at the beginning of the background.js script to help me track it. I've also attached the result.

// background.js
// Import Firebase dependencies

const BACKGROUND_INSTANCE_ID = Math.random().toString(36).substring(7);
console.log(`Background script initialized with ID: ${BACKGROUND_INSTANCE_ID}`);

// Use a flag to track whether a listener has been registered
let listenerRegistered = false;

// Check if a listener is already registered in this Chrome session
chrome.storage.local.get(['listenerRegisteredAt'], (result) => {
  const now = Date.now();
 
  // If no listener is registered or it was registered more than 5 minutes ago (handle stale registrations)
  if (!result.listenerRegisteredAt || (now - result.listenerRegisteredAt > 300000)) {
    // Register our listener
    if (!listenerRegistered) {
      registerMessageListener();
     
      // Update the registration timestamp
      chrome.storage.local.set({
        listenerRegisteredAt: now,
        currentBackgroundId: BACKGROUND_INSTANCE_ID
      });
     
      console.log(`[Instance ${BACKGROUND_INSTANCE_ID}] Message listener registered`);
    }
  } else {
    console.log(`[Instance ${BACKGROUND_INSTANCE_ID}] Listener already registered recently. Skipping registration.`);
   
    // Check if we can recognize the current active instance
    chrome.storage.local.get(['currentBackgroundId'], (idResult) => {
      if (idResult.currentBackgroundId) {
        console.log(`[Instance ${BACKGROUND_INSTANCE_ID}] Active instance is: ${idResult.currentBackgroundId}`);
      }
    });
  }
});

// Main message handler
function registerMessageListener() {
  if (listenerRegistered) return;
 
  // Set the flag first to prevent race conditions
  listenerRegistered = true;
 
  chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    console.log(`[Instance ${BACKGROUND_INSTANCE_ID}] Background received message:`, request);
    console.group("Message Received");
    // console.log("Request object:", request);
    // console.log("Sender object:", sender);
    // console.trace("Stack trace:");
    console.groupEnd();

    const handleError = (error) => {
      console.error(`Error in ${request.action}:`, error);
      return {
        success: false,
        error: error.message,
        errorCode: error.code || 'UNKNOWN_ERROR'
      };
    };

    // Handle authentication requests
    if (request.action === 'initAuth') {
      (async () => {
        try {
          await initFirebase();
          sendResponse({ success: true });
        } catch (error) {
          sendResponse({ success: false, error: error.message });
        }
      })();
      return true;
    }
   
    if (request.action === 'emailSignIn') {
      (async () => {
        const result = await handleEmailSignIn(request.data);
        sendResponse(result);
      })();
      return true;
    }
   
    if (request.action === 'emailSignUp') {
      (async () => {
        const result = await handleEmailSignUp(request.data);
        sendResponse(result);
      })();
      return true;
    }
   
    if (request.action === 'googleSignIn') {
      (async () => {
        const result = await handleGoogleSignIn();
        sendResponse(result);
      })();
      return true;



promptfast error.png

Thank you!

woxxom

unread,
Mar 7, 2025, 9:05:00 PMMar 7
to Chromium Extensions, Justice Chinedu, woxxom
According to the screenshot in your first screenshot it prints the same message with "instance" prefix and without it, so it looks like you have another listener that does it. It's still unclear whether this is the complete code, so maybe you should just upload everything.

Justice Chinedu

unread,
Mar 28, 2025, 8:20:13 AMMar 28
to Chromium Extensions, woxxom, Justice Chinedu
Thanks for your response woxxom. Sorry, I've not responded for quite a while. I was out on national duties. However, I later figured it out.

I implemented a solution that  uses a message caching system that tracks recent messages by creating unique keys for each request. When a message arrives, it checks if an identical message was processed recently (within a configurable time window - 2 seconds).

Also, non-critical actions are filtered out if duplicated, while critical operations (like authentication) are allowed to proceed even if duplicated. This prevents the background script from processing the same request multiple times, which had been causing UI elements and data to be duplicated.


But, thank you for your time and effort. I really do appreciate the help!
Reply all
Reply to author
Forward
0 new messages