Regression Bug - JavaScript not executing correctly when triggered from Context Menu

Hi @Andreas_Hegenberg - hope you are well :slight_smile: Reporting a regression bug that I found.

Describe the bug

  • When I click on a custom context menu item to executed a named trigger that runs JavaScript and makes a fetch request, the script execution stalls and seemingly times out after a while. No error message is shown.
  • Downgrading to version 4.270 fixes the issue

Affected input device (e.g. MacBook Trackpad, Magic Mouse/Trackpad, Touch Bar, etc.):

  • Automation & Named & Other Triggers
  • Keyboard Shortcuts

Here are some steps to replicate the issuee:

My custom context menu:

One of the menu items triggers the named trigger that then runs JavaScript and makes a Fetch request to OpenAI.

And this is the named trigger that makes a request to OpenAI

  • Points to note:
    • Clicking on Test Execute runs the script successfully with the expected result
    • Changing the named trigger to be executed when e.g., "moving the mouse cursor to the top left of the screen also works.
  • However, when using it as a named trigger that gets triggered when one clicks on the respective context menu, the first showHUD function executes, but then the script stalls most likely trying to make the fetch request.
  • Unfortunately, there no error message is ever shown.
  • Downgrading to version 4.270 fixed it for me though

Device information:

  • Type of Mac: MacBook Pro 16-inch, 2021
  • macOS version: Ventura 13.6
  • BetterTouchTool version:

I've tried the following versions:

  • 4.273 (latest) => Bug is present
  • 4.272 => Bug is present
  • 4.270 => Bug is NOT present

Additional information (e.g. crash logs, related issues, etc.):

  • The app doesn't crash, but it seems that any external fetch request within the JavaScript execution is stalling.

Thanks for everything you do with BTT :slight_smile:

Quick question: are you using the "Show Custom Context Menu (New)" or the "Show Custom Context Menu (Old)" action?

Unrelated: Are you aware of the dedicated ChatGPT actions?

Thanks for the swift reply @Andreas_Hegenberg:

  • I am using the "Show Custom Context Menu (New)"
  • Yes, I'm aware there is a dedicated ChatGPT action, but my script has extra functionality that I rely on as part of calling OpenAI
1 Like

very weird, I can't seem to reproduce it with the same/similar setup. (Context menu => Named Trigger => Transform & Replace...)

I made some little changes in 4.274 alpha, would be great if you could try that one.

Thanks @Andreas_Hegenberg - I've downloaded the new version, but encounter the same bug. I've now used BTTLog() and did some further investigation why this error happens and think I found the culprit:

Here are some screenshots that show what is happening:

  1. When running the JavaScript triggered from the new context menu, it starts the script and makes the correct BTTLog() call, but then for some reason it calls the wrong fetch request from a menu bar item that has nothing to do with the current script. Perhaps the fetch request is someone pre-cached? Or because it's an anonymous function it gets confused? In any case, you can see in the log that the response I'm getting is the response to currency rates instead of the one from OpenAI that I'd expect.

  2. When executing the script via the "Test Execute" button, it works correctly and I get the correct response from the fetch request.

  3. FYI - Here is one of the other menubar items that I have in my BTT setup that makes fetch requests to other APIs.

For completeness, let me also share the OpenAI script that I'm trying to run:

async (clipboardContentString) => {
    // ------------------------------------------------
    // ------------------------------------------------
    const OPENAI_API_KEY = "<REDACTED>";

	// here you can pre-configure the AI with some configuration prompt:
    const BEHAVIOR_DESCRIPTION = await callBTT('get_string_variable', {variable_name:'GPTSystemPrompt'}) || "Be my helpful AI"
    const GPT_TEMPERATURE = Number(await callBTT('get_string_variable', {variable_name:'GPT_Temperature'}) || 0.2)

    // ------------------------------------------------
    // CODE  starts here (no change required)
    // ------------------------------------------------

    let previousChat = [];

    showHUD(`${BEHAVIOR_DESCRIPTION}...`, "brain", 100);

    try {
    		previousChat.push({"role": "system", "content": BEHAVIOR_DESCRIPTION});
    	previousChat.push({"role": "user", "content": clipboardContentString ? clipboardContentString : ''});
         BTTLog("************ Making fetch request...")
	const response = await fetch("", {
        		method: "POST",
        		headers: {
        	    		"Content-Type": "application/json",
        	    		"Authorization": `Bearer ${OPENAI_API_KEY}`,
        		body: JSON.stringify({
        	    		model: "gpt-3.5-turbo",
        	    		messages: previousChat,
            		temperature: GPT_TEMPERATURE

        BTTLog("************ Fetch request completed...")
        const data = await response.json();
        const text = data.choices[0].message.content;

        showHUD(`Total tokens: ${data.usage.total_tokens}`, "", 1, "Success");

        return `${clipboardContentString} \n\n${text}`;
    } catch (error) {
        showHUD(`${error.message}`, "", 10, "Error");
        return "Error";

    function showHUD(text, icon, duration, title) {
        const hudConfig = {
        		BTTActionHUDHideWhenOtherHUDAppears: true,
        		BTTActionHUDDetail: text,
        		BTTIconConfigSFSymbolName: icon,
        		BTTActionHUDDuration: duration,
        		BTTActionHUDSlideDirection: 0,
        		BTTIconConfigImageHeight: 0,
        		BTTActionHUDTitle: title ? title : '',
        		BTTIconConfigIconType: 2,

        const actionDefinition = {
     	   	BTTWaitForReply: false,
       	 	BTTPredefinedActionType: 254,
      	  	BTTHUDActionConfiguration: JSON.stringify(hudConfig),

        callBTT("trigger_action", { json: JSON.stringify(actionDefinition) });

ah that's an interesting observation, maybe I have an idea.

By the way, you can also use console.log in any BTT javascript - these can be viewed via Safariโ€˜s develop menu (if developer menu is enabled in Safari)

1 Like

Would be great if you could try 4.275 (uploading now). Testing a few things here - not yet completely sure whether that will solve the issue.

I believe previously all Java Script functions were sharing one instance of my XMLHTTPRequest class, which could lead to weird issues. Now a separate one is created for every request.

1 Like

Thanks - I've tested the new version and here are my findings:

  1. The Reusable Named Trigger JavaScript now completes when triggered from a custom context menu item (new) and the HUD message disappears indicating that the fetch request goes through, however, it doesn't return the text correctly and replace the selection as before. Hence, nothing is shown in the application such as the note app.

  1. I've then tried out to see what happens if I change this script from a Reusable Named Trigger to be triggered by Rick Click Full Screen Icon.
  • To my surprise that returned the correct result as you can see in the video above.
  1. I've also tried to change the same script from being triggered by Rick Click Full Screen Icon to Move Mouse To Top Left Corner and noticed that the script returned the following:

I'm not exactly sure why using different triggers to run the Transform & Replace Selection with JavaScript action would cause different behaviors in terms of how the script is executed and what is return, but hope this report can help to find it out :slight_smile:

Perhaps there is still a duplicate XMLHTTPRequest created? Speaking about that, my Euro <> HKD script is currently set to Execute script every 0 seconds and Always run when widget becomes visible.

Ah thanks for the details! That most likely is a window focus problem now. I had to make some changes for macOS Sonoma, possibly they don't work well on older systems.
(BTT tries to copy the selected text via cmd+c (and paste the transformed via cmd+v), which only works if the active window still has keyboard focus. However keyboard focus gets disrupted by showing a context menu.).

I'll try on my macOS 13 machine later!

1 Like

Absolutely, thanks for your help to fix this :slight_smile: much appreciated!

I'm not sure if the issues left are entirely focus related though, allow me explain:

  1. I'm still seeing data being returned from an entirely different script that is executing in a cron like fashion. However, this only happens when I trigger my JavaScript through Move Mouse To Top Left Corner.

  2. I just did a quick test on the focus hypothesis:

  • Running Transform & Replace Selection With Java Script I can see that the clipboardContentString is picked up correctly using CMD + C
  • While the script is running I've tried to restore focus to the notes app by clicking into it, but didn't see any text being return (this used to work in previous BTT versions as I recall switching between different apps before and the script returning data in the app that was currently active)
  • I've also tried to disable all showHUD calls to see if that makes a difference, but it didn't unfortunately


I had to make some changes for macOS Sonoma, possibly they don't work well on older systems.

Just reading this again, perhaps it is related to these changes indeed. I don't know the exact implementation details, hence, just stumbling in the dark with my guessing!

I will only get to test on my macOS 13 machine tomorrow but just uploaded 4.276 alpha which should only apply the changes to Sonoma.

Thanks again @Andreas_Hegenberg - I'll give it a try on my other Sonoma machine tomorrow as well to see if there are any differences that I spot. Have a nice rest of your day :slight_smile:

Hi @Andreas_Hegenberg hope you're having a good weekend. I've tried it out on my macOS Sonoma machine and while the fetch request works there, the replace text is not working as the Custom Context Menu (NEW) removes the focus as you mentioned.

Have you had any luck on your side with testing? Thanks

On Sonoma everything seems to work fine here with the latest alpha. BTT should automatically activate the previous window again when the context menu executes its action.
Did you also try with the alpha on Sonoma?