# Detecting and Recording Macro Errors

You can control how a macro responds when an error occurs during execution. By creating and adding an onError macro to your macro file, you can specify that, on the occurrence of an error, macro execution within the current macro stops and the onError macro is invoked. An onError macro can call other macros. If another error occurs after the onError macro is invoked, macro execution stops again and the onError macro is invoked again. This process continues either until the onError macro completes or until reaching the recursion limit of 10.

## Detectable Macro Errors

CLI macros detect various errors when a macro is executed. Some of these errors are detected without the use of an onError macro; they include the following:

- Macro file not found
- Macro not found
- Macro compilation error
- Macro does not complete error due to excessive looping or recursion

The following errors are detected only when a CLI macro file contains an onError macro:

- Syntactic error in executed CLI command
- Runtime error in executed CLI command

In addition to these detectable errors, you can use the following environment commands to return textual error information to the macroData log file:

- env.getErrorCommand
- env.getErrorStatus

  | Caution: Though you can use the env.getErrorCommand and env.getErrorStatus commands in any macro, the only appropriate place from which to execute these commands is from an onError macro.

## Logging Macro Results

You can use the env.setResult command to set parameters within a macro to display information through the macroData log file. When defined, parameter information appears in the macroData log file at the NOTICE severity level following the completion of the macro.

The following example defines several results (1 through 5):

<# numberMacro #><# env.setResult("A", “ “ $1 ) #><# env.setResult("A", “ “ $2 ) #><# env.setResult("A", “ “ $3 ) #><# env.setResult("A", “ “ $4 ) #><# env.setResult("A", “ “ $5 ) #><#endtmpl#>

Each value is sent to the macroData log file, starting with 1 and ending with 5. Each successive value overwrites the previous value in the log file. In other words, if the macro ends after setting the third result (that is, 3) the log file displays the following:

A is 3

If the macro finishes completely, the log file displays the following:

A is 5

## Viewing Macro Errors

You can view macro error information in the macroData log file using the show log data command and specifying the macroData keyword for the category.

| Note: Each execution of a macro, by any user and by any name, obtains a unique ID. This ID appears in the starting and ending message of the macro output and for each log message in the macroData log.

show log data

- Use to display log event data using the category keyword and the macroData category.
- delta—Limits the display to events that occurred after the time set with the log baseline command.
- severity—Displays events that have a specific severity level.
- Example

      host1(config)# show log data category macroData severity debug
      NOTICE 01/07/2006 09:46:57 macroData: Macro 'badInterfaceCommandMacro' in file 'testInterfaceCommand.mac' starting execution (Id: 402) on vty, 0
      ERROR 01/07/2006 09:46:57 macroData: (Id: 402) Command error:  interface fastEthernet 500, Command execution error
      NOTICE 01/07/2006 09:46:57 macroData: (Id: 402) commandError is interface fastEthernet 500
      NOTICE 01/07/2006 09:46:57 macroData: (Id: 402) commandErrorStatus is Command execution error
      NOTICE 01/07/2006 09:46:57 macroData: (Id: 402) runStatus is Loop:500
      NOTICE 01/07/2006 09:46:57 macroData: Macro 'badInterfaceCommandMacro' in file 'testInterfaceCommand.mac' ending execution (Id: 402) on vty, 0

- See show log data.

## onError Macro Examples

The following examples provide an indication of how the onError macro can assist in using and troubleshooting macro files. The examples purposely contain errors and show the result when using the onError macro.

### Detecting Invalid Command Formats

In this example, the following macro file (badInterfaceCommand.mac) performs a loop. Within each loop, the CLI executes the interface fastEthernet command using an invalid interface format:

<# badInterfaceCommandMacro #><# env.setResult("runStatus","start" ) #><# theLoopCount := 500 #>conf t <# while theLoopCount > 0 #> <# env.setResult("runStatus", "Loop:" $ theLoopCount ) #> interface fastEthernet <# theLoopCount; '\n' #> <# --theLoopCount #> <# endwhile #><# env.setResult("runStatus","complete" ) #><#endtmpl#><# onError #><# env.setResult("commandError", env.getErrorCommand) #><# env.setResult("commandErrorStatus", env.getErrorStatus) #><#endtmpl#>

If the macro were to run to completion, the CLI would execute the commands as follows:

interface fastEthernet 500 interface fastEthernet 499...interface fastEthernet 1

Because the macro uses invalid interface formats, executing the macro without the embedded onError macro would result in error output for each loop. However, the onError macro detects the error and stops the macro. Using the onError macro, the output appears as follows:

    host1(config)# macro testInterfaceCommand.mac badInterfaceCommandMacro
    Macro 'badInterfaceCommandMacro' in file 'testInterfaceCommand.mac' starting execution (Id: 402)
    Enter configuration commands, one per line.  End with ^Z.
    ERX-40-94-fb(config)#interface fastEthernet 500
                                                ^
    % invalid interface format
    Macro 'badInterfaceCommandMacro' in file 'testInterfaceCommand.mac' ending execution (Id: 402)

You can determine the execution progress through the runStatus result entry in the macroData log file. For this example, the runStatus value of 500 indicates that the macro ended early.

    host1(config)# show log data category macroData severity debug
    NOTICE 01/07/2006 09:46:57 macroData: Macro 'badInterfaceCommandMacro' in file 'testInterfaceCommand.mac' starting execution (Id: 402) on vty, 0
    ERROR 01/07/2006 09:46:57 macroData: (Id: 402) Command error:  interface fastEthernet 500, Command execution error
    NOTICE 01/07/2006 09:46:57 macroData: (Id: 402) commandError is interface fastEthernet 500
    NOTICE 01/07/2006 09:46:57 macroData: (Id: 402) commandErrorStatus is Command execution error
    NOTICE 01/07/2006 09:46:57 macroData: (Id: 402) runStatus is Loop:500
    NOTICE 01/07/2006 09:46:57 macroData: Macro 'badInterfaceCommandMacro' in file 'testInterfaceCommand.mac' ending execution (Id: 402) on vty, 0

### Detecting Invalid Commands

In this example, the following macro file (badExecCommand.mac) is programmed to executes four exec mode commands. However, the second command in the sequence is invalid.

<# badExecCommandMacro #><# env.setResult("runStatus","start" ) #>show clock<# env.setResult("runStatus","after first show clock" ) #>foo<# env.setResult("runStatus","after foo" ) #>show privilege<# env.setResult("runStatus","after show privilege" ) #>show clock<# env.setResult("runStatus","complete" ) #><#endtmpl#><# onerror #><# errCmd := env.getErrorCommand #><# errStatus := env.getErrorStatus #><# env.setResult("commandError", errCmd) #><# env.setResult("commandErrorStatus", errStatus) #><#endtmpl#>

If the macro were to run to completion, the following commands would be executed:

show clock foo show privilege show clock

Without the onError macro, the macro would indicate the invalid command, but it would also continue with the rest of the configuration. When using the onError macro, the macro stops when it encounters the invalid command.

Executing the macro that contains the onError macro, the output appears as follows:

    host1# macro badExecCommandTest.mac badExecCommandMacro
    Macro 'badExecCommandMacro' in file 'badExecCommandTest.mac' starting execution (Id: 101)
    SUN JAN 08 2005 07:21:50 UTC
    ERX-40-94-fb#foo
                 ^
    % Invalid input detected at '^' marker.
    Privilege level is 15
    Macro 'badExecCommandMacro' in file 'badExecCommandTest.mac' ending execution (Id: 101)

You can determine the execution progress through the runStatus result entry in the macroData log file. For this example, the log output indicates the command error and displays the following to indicate that the macro ended early:

runStatus is after foo

    host1# show log data category macroData severity debug
    NOTICE 01/08/2006 07:14:13 macroData: Macro 'startmin' in file 'master.mac' starting execution (Id: 1) on vty, 0
    NOTICE 01/08/2006 07:14:18 macroData: Macro 'startmin' in file 'master.mac' ending execution (Id: 1) on vty, 0
    NOTICE 01/08/2006 07:21:50 macroData: Macro 'badExecCommandMacro' in file 'badExecCommandTest.mac' starting execution (Id: 101) on vty, 0
    ERROR 01/08/2006 07:21:50 macroData: (Id: 101) Command error: foo, Command syntax error
    NOTICE 01/08/2006 07:21:50 macroData: (Id: 101) commandError is foo
    NOTICE 01/08/2006 07:21:50 macroData: (Id: 101) commandErrorStatus is Command syntax error
    NOTICE 01/08/2006 07:21:50 macroData: (Id: 101) runStatus is after foo
    NOTICE 01/08/2006 07:21:50 macroData: Macro 'badExecCommandMacro' in file 'badExecCommandTest.mac' ending execution (Id: 101) on vty, 0

### Detecting Missing Macros

In this example, the following macro file (badMacroInvocation.mac) is programmed to invoke a missing or nonexistent macro (tmpl.foo).

<# badMacroInvocation #><# env.setResult("runStatus","start" ) #><# tmpl.foo #><# env.setResult("runStatus","complete" ) #><#endtmpl#><# onerror #><# errCmd := env.getErrorCommand #><# errStatus := env.getErrorStatus #><# env.setResult("commandError", errCmd) #><# env.setResult("commandErrorStatus", errStatus) #><#endtmpl#>

When using the onError macro, the macro stops when it encounters the missing macro. The output appears as follows:

    host1# macro badMacroInvocation.mac badMacroInvocation
    Macro 'badMacroInvocation' in file 'badMacroInvocation.mac' starting execution (Id: 407)
    % can't find macro foo
    Macro 'badMacroInvocation' in file 'badMacroInvocation.mac' ending execution (Id: 407)

You can determine the execution progress through the runStatus result entry in the macroData log file. For this example, the log output indicates the macro error and displays the following to indicate that the macro ended prior to invoking the macro:

start

    host1# show log data category macrodata severity debug
    NOTICE 05/27/2005 12:39:10 macroData: Macro 'badMacroInvocation' in file 'badMacroInvocation.mac' starting execution (Id: 407) on vty, 0
    ERROR 05/27/2005 12:39:10 macroData: (Id: 407) Command error: foo, macro not found
    NOTICE 05/27/2005 12:39:10 macroData: (Id: 407) commandError is foo
    NOTICE 05/27/2005 12:39:10 macroData: (Id: 407) commandErrorStatus is macro not found
    NOTICE 05/27/2005 12:39:10 macroData: (Id: 407) runStatus is start
    NOTICE 05/27/2005 12:39:10 macroData: Macro 'badMacroInvocation' in file 'badMacroInvocation.mac' ending execution (Id: 407) on vty, 0