Numbered steps to allow referencing when macro fails

I have many macros that have 100+ steps. When I get a notification that the macro broke/failed, I have no way to know where it failed / which step.
If the steps in each macro were numbered, the notification could say "failed at step #___" and this would facilitate much easier debugging.
It would also allow a more customizable flow structure, for example with a command "if x then go to step #y"

Switch to the KM Editor and select "Go to Last Aborted Action" from the "View" menu -- that'll jump you to the last action that failed.

There's been a bunch of other methods posted on the Forum -- this thread came up first in a search, but I know there have been others.

I'm going to say "Please, no!" to this. Using GOTOs usually results in a program (or macro) that is harder to understand, debug, and maintain -- so-called "spaghetti code".

It wouldn't be so bad in a macro of even 100+ actions, but you're still better off reorganising your macro's control flow so you don't need to jump around arbitrarily.

5 Likes

I do this all the time using a While loop that encases a Switch action. The switch action decides which block of code to execute using a "State variable", and each block of the Switch action changes the value of the State variable, which essentially means I have implemented a GOTO action. You can see an example of it here:

Hey thanks! Bit of a learning curve there for me but that's a completely novel idea.
I realized also there is another way; to create a new macro and have it trigger with an if-then. The new macro instructs to cancel all other macros as its first step.

Switch to the KM Editor and select "Go to Last Aborted Action" from the "View" menu -- that'll jump you to the last action that failed.

ah, thanks I was not aware of that function.

I'm going to say "Please, no!" to this. Using GOTO s usually results in a program (or macro) that is harder to understand, debug, and maintain -- so-called "spaghetti code".

ok. Figured out a workaround my creating new macros for the "chunks" and using if-then to trigger them and cancel the previous.

I'd love to understand your idea. Can you upload a sample macro to demonstrate this? I can't understand how to write such a macro.

It's tough to understand because "Cancel All Other Macros" does NOT cancel any other macros that are in the same instance. Are you perhaps suggesting that the solution is to call macros asynchronously?

I'm on the wrong computer but it's simple, maybe I didn't explain very clearly:

If the variable [varname] is [value], execute the following [trigger macro by name].

And then the first step of the new macro is to cancel all other macros.

Then it's a case of just copy pasting the required sequence of steps into the new macro and removing them from the existing.

Of course it doesn't have to be a variable; it could be spreadsheet cell data copied into a named clipboard, etc.

Hope that makes sense!

The error will generally include the action number, and other than the editor’s View ➤ Go to Last Aborted Action, you can also search for action:NNNN to find the offending action.

2 Likes

I guess I didn't explain myself very clearly. The "Cancel all Other Macros" action does NOT cancel the macro that called the current macro, because it's in the same instance. This is why I can't implement your idea.

Did you test your idea yet? Or is it just an idea so far?

I've been using it round the clock, works great.
Well that was unexpected: It's a bit illogical to title something "cancel all other macros" that does not, in fact, cancel all other macros.
Is this surprising feature actually noted in the instructions? Or have I inadvertently found another bug? :wink:

There are several variants of the Cancel Macros action:

If Cancel All Other Macros canceled the parent of macro of this macro, then that would also cancel this macro, and result in it behaving the same as Cancel All Macros.

You could, perhaps, use the Execute a Macro action to execute a submacro ascynronosuly (which would then be its own macro instance) and then from within it Cancel All Other Macros.

But I am somewhat confused as to what you expect to happen with the parent macro in the case of the Cancel All Other Macros. If you don't want it to run any further, then don’t return to it.

I'm also more than a little confused as to what sort of structure you are trying to create.

2 Likes

As I said, the documentation for "Cancel all Other Macros" says, "except this macro instance." So it specifically does say it does not cancel the parent macro. So yes, this is noted in the instructions.

On a separate page it defines "macro instance" as follows:

...the macro instance (ie, that macro and all the macros that it executes)

I understand what you want, which is not unreasonable, but we all have to work with the way KM works.

As Peter and I suggested, it might be possible to do what you want by running your child macros asynchronously. But that will introduce a new problem, which I'm not sure you are ready to face.

You can't actually cancel macros, you can only cancel executing instances of macros. But putting all that in an action's name gets a bit clunky!

Now you know it's based on executing instances you'll see that what happens depends on how the macro with the "Cancel" action was called:

  • If it was by "Execute a Macro" with the "Asynchronously" option turned off then the called macro is the same executing instance as the caller -- the caller will not be cancelled
  • If it was by "Execute a Macro" with the "Asynchronously" option turned on then the called macro is a different executing instance to the caller -- the caller will be cancelled

Ok I understand now. My bad. I was using cancel all macros, (which cancels all the other macros).