Today I discovered a macro I had written some time ago that used a keyword in the script return variable to detect an error: "[ERROR]".
So, instead of checking for no errors (ala "OK"), this checks specifically for an error. In any case it does NOT change the return variable.
Obviously, I like both ways. But, after thinking about it, and using it some, I'm starting to like the check for "[ERROR]" better. This also allows another error return of "[USER_CANCELED]", which may need to be handled different, especially in reporting the results to the user.
So here is yet another alternated method of script error handling in a KM Execute Script Action.
####I'd love feedback from all interested as to which method you like best.
### RETURNS a POSIX path like "/Users/Shared/Dropbox/" ###
property propScriptName : "Choose Folder & Return POSIX Path"
set promptStr to "Choose a FOLDER"
set x to 0
--set y to 1/x
set folderPath to POSIX path of (choose folder with prompt promptStr)
on error errMsg number errNum
if errNum = -128 then ## User Canceled
set folderPath to "[USER_CANCELED]" & return & return & "SCRIPT: " & propScriptName
set folderPath to "[ERROR]" & return & return & "SCRIPT: " & propScriptName & return & "Number: " & errNum & return & errMsg
If you’re going to return results, as opposed to setting KM variables, then this method is OK as long as an empty result is not valid. But if there’s ever a time when an empty result is valid, then you can’t use this method, because there’s no way to guarantee that the script actually ran.
Regardless, I don’t see a problem with returning things like “user canceled” in the result - that’s cool. But, in your example, you combine them all into one general-purpose error message, so I don’t see the point.
By the way, you should verify that whatever method you choose (in JXA scripts) works correctly in that Yosemite environment that causes the strange warnings.
And just to verify that I’m thinking correctly, we should ALWAYS (in JXA) wrap everything in a try/catch, then “return” the error message, rather than let the error bubble up via stderror, because we generally turn off “return errors” (because of the Yosemite issue), right?
One of the cardinal rules to being a good developer is to understand that you can’t know everything. I have no idea if it could return nothing, and have not run successfully. But I would never make an assumption one something like this that I don’t need to. And I don’t need to. If it doesn’t return “OK”, something failed. End of story.
One of the reasons I am adamant about things like this, is because I want to get it right and never think about it again. I want to know I’ve accounted for everything I can, even the unforeseen, if possible. I want the code to tell me when there’s a problem. I don’t want to have to guess about it.
But as I wrote to someone else today, we’re not creating mission-critical software. I know you, of all people, know all about that. So in the end, it’s all good. Do what feels right to you. If it ends up not working, you’ve got other options.
OK. I can’t argue with that. So, bottom line, is that all scripts should return something, with “OK” being the minimum if the script completely successfully (for macros that use the results in further Actions). Unless, of course, the point of the script it to set the Clipboard, or just display results.
So, to combine our approaches, we could do this:
Test for “OK”, “^[OK]”, “^[ERROR]”, “^[USER_CANCELED]”, or other text.
If we get nothing, i.e. a blank result, then treat that as an error.
(I have used “^” to denote at the start of the return string.)
Well, I’m good with that, although I’d only check for OK - everything else is an error as far as I’m concerned, with the possible exception of things that actually can be canceled, which aren’t that many.
But if you go this way, it means you don’t return actual values via “return”. Personally, I’m good with that, but I didn’t think you were, so I want to remind you.
I’m sure most people would consider that overkill. Not me, obviously, but I’m used to people looking at me funny. Maybe you should think on it for a day or two, before you sit at the weird kids’ table.
By the way, I had a personal chuckle today. I was talking about how we weren’t actually writing mission-critical apps, and that made me think of you. That phrase probably means more to you than to me!
The reason I like to use the KM Action option to “return results to variable” is that it makes it easy, and less error prone, for the user to set the KM variable of their choice. There are many scripts that are general purpose, like choosing file and folder, and I think it is best for the user to not have to change the script to set a different KM variable.
Due to the nature of Keyboard Maestro, I don’t think I’d write any process using it that is truly mission critical. Of course, Peter might disagree with me.
First, @JMichaelTX thanks for sharing your template. I also appreciate the discussion regarding the pros and cons of each approach.
The V4.1 template works perfectly on my MacBook Pro 16" (Big Sur 11.3.1 using KM 9.2).
On my Mac mini (Late 2012) (Mojave 10.14.6 also using KM 9.2), however, the template returns:
~~~ VARIABLE from Script Results ~~~
objc: Class FIFinderSyncExtensionHost is implemented in both /System/Library/PrivateFrameworks/FinderKit.framework/Versions/A/FinderKit (0x7fff9d1323f0) and /System/Library/PrivateFrameworks/FileProvider.framework/OverrideBundles/FinderSyncCollaborationFileProviderOverride.bundle/Contents/MacOS/FinderSyncCollaborationFileProviderOverride (0x110386f50). One of the two will be used. Which one is undefined.
Note, if I copy the AppleScript code to the Script Editor, I get the expected:
~~~ VARIABLE from Script Results ~~~
It is a warning the system puts out because Apple chose to implement a specific class, FIFinderSyncExtensionHost, in both of two different Apple Frameworks, both of which happen to be used in this process (indirectly, they are private frameworks so not used directly).
It is essentially an Apple bug, though hopefully harmless (assuming both implementations are identical, otherwise it could have interesting quirky bugs).
Presumably Apple resolved the bug between Mojave and Big Sur which is why you don't see it in Big Sur, thus no need to turn off “Include Errors” - note that Include Errors chooses whether the output of the script is just the stdout, or also includes stderr error stream.