Error: API misuse: modification of a menu's items on a non-main thread



I just changed the version number of an Enhanced Applet, and now I get this error message when I run it:

API misuse: modification of a menu’s items on a non-main thread when the menu is part of the main menu. Main menu contents may only be modified from the main thread.

I’m using code like this in the main thread which worked for years:

		set appMenu to (current application's NSApp's mainMenu()'s itemAtIndex:0)'s submenu()
		set menuItem to (current application's NSMenuItem's alloc()'s initWithTitle:"Einstellungen …" action:"showPrefs:" keyEquivalent:",")
		menuItem's setTarget:me
		appMenu's insertItem:menuItem atIndex:2
		set appMenu to (current application's NSApp's mainMenu()'s itemAtIndex:0)'s submenu()
		set menuItem to (current application's NSMenuItem's alloc()'s initWithTitle:"Einstellungen zurücksetzen" action:"resetPrefs:" keyEquivalent:"")
		menuItem's setTarget:me
		appMenu's insertItem:menuItem atIndex:3

The error occurs in all my Applets, when I recompile them. So it must be caused by a Script Debugger or macOS update.

I tried it with SD 8.0.6 and my Applets compiled without producing this error message. So something must have changed in the Enhanced Applet which is not documented in the release notes.

We made no changes to the Enhanced Applet shell between Script Debugger 8.0.6 and 8.0.7. Any difference you are seeing may be caused by changes to the macOS SDK we are linking against which probably did change.

So I can’t update SD anymore or is there a chance that Apple will fix the SDK in the future? Are there other ways to have custom menu commands?

AppleScript, which creates and calls items in the status menu, was written in 2017, and to this day there have been no problems running it with Script Debugger.

There are many Cocoa APIs that need to be called in the main thread. These include NSAlert, NSMenu, and WkWebView.
I also use Script on a daily basis with the Script Debugger to create a menu item in the Status menu and generate the menu item under it.

The Script Editor has the ability to force the main thread to run, but the Script Debugger does not.

However, the functions that need to be called in the Main thread are put together in a handler,

my performSelectorOnMainThread:“dispStatusMenu:” withObject:(paramObj) waitUntilDone:true

By calling it like this, it can be executed on Script Debugger without causing an error.

1 Like

As @Piyomaru says, you need to explicitly move execution to the main thread when using Cocoa APIs that require they be used on the main thread. The Enhanced Applet Shell has always executed user scripts on a background thread in order to keep its UI responsive. Script Debugger also runs user scripts on a background thread for this and other reasons.

Hi and thanks for your answers. So, since SD 8.0.7 the run handler is not the main thread anymore? Why does it work in older Versions? It worked fine for some years using those commands in the run handler.

But anyway, using performSelectorOnMainThread was the solution. Thanks.

The run handler was never invoked on the main thread. The menu API thread misuse error has always been present and is not being reported by macOS.

So, I always did it the wrong way and SD forgot to blame me over the years? :thinking: I have never seen this message before, and I always don’t really understand what I’m doing. :grin:

Script Debugger is not aware of the main-thread requirements of Cocoa APIs because Script Debugger does not participate in the compilation of AppleScript code - that is handled by Apple’s AppleScript compiler. Main-thread requirements are available in the Apple documentation. More recently the macOS SDK has started reporting these problems.

Xcode has had a Thread Sanitizer feature for a number of years that generated warnings when main-thread APIs were called on background threads.

In generally, anything that touches the UI in any way must be run on the main thread.

A good example of this sort of thing is my DialogToolkit scripting library. I initially called some stuff off the main thread because it was simpler, and they were APIs that had never thrown an error in Objective-C or AppleScriptObjC. Then after one upgrade they started throwing warnings, and after another they stopped working altogether.