Handling known exceptions

Exceptions are unexpected events that disrupt a bot's runtime. Although unexpected, the developer can predict these events. This section describes how to handle known exceptions in your IBM RPA script.

You can handle known exceptions by:

  • Handling the exception event with the Handle Error (onError) command.
  • Using flow control conditional commands for validation.

For example, consider the following script: unhandled_division. You can copy the following script and paste it in the Script tab of IBM RPA Studio.

defVar --name text_dividend --type String
defVar --name text_divisor --type String
defVar --name num_dividend --type Numeric
defVar --name num_divisor --type Numeric
defVar --name quotient --type Numeric
// Prompt user for dividend and divisor. 
// Perform division of dividend by divisor and show quotient.

inputBox --title "The dividend" --prompt "Enter the dividend" text_dividend=value
convertStringToNumber --text "${text_dividend}" --allowleadingsign  --allowdecimalpoint  --allowthousands  num_dividend=value
inputBox --title "The divisor" --prompt "Enter the divisor" text_divisor=value
convertStringToNumber --text "${text_divisor}" --allowleadingsign  --allowdecimalpoint  --allowthousands  num_divisor=value
evaluate --expression "${num_dividend} / ${num_divisor}" quotient=value
messageBox --title "The quotient" --text "${num_dividend} / ${num_divisor} = ${quotient}" --icon "Information" --buttons "OK" --defaultbutton "FirstButton"

The unhandled_division script relies on user input to perform a division and show the result. Relying on raw user input can become troublesome if the bot doesn't validate the input.

The Convert Text to Number (convertStringToNumber) command converts a text variable into a number variable. The command assumes the text variable has the expected pattern, which needs to be a number. However, the Input Box (inputBox) command accepts any text input from the user. In unhandled_division, a runtime exception will happen if the user enters anything other than a number in the input dialog window.

We can classify the event of entering the wrong input as a known exception since it disrupts the bot's runtime, but we can handle it properly. You could handle this exception by:

  • Catching the exception
  • Validating the user input

Handling the exception

In the unhandled_division script, you could handle the exception like in the following script:

defVar --name text_dividend --type String
defVar --name text_divisor --type String
defVar --name num_dividend --type Numeric
defVar --name num_divisor --type Numeric
defVar --name quotient --type Numeric
defVar --name dividend_acquired --type Boolean
defVar --name divisor_acquired --type Boolean
// Perform division of dividend by divisor and show quotient.

goSub --label get_user_input_for_dividend
goSub --label get_user_input_for_divisor
goSub --label evaluate
messageBox --title "The quotient" --text "${num_dividend} / ${num_divisor} = ${quotient}" --icon "Information" --buttons "OK" --defaultbutton "FirstButton"
beginSub --name get_user_input_for_dividend
// Prompts user for dividend input until acquired successfuly or user aborts.
	while --left "${dividend_acquired}" --operator "Is_True" --negate
		inputBox --title "The dividend" --prompt "Enter the dividend (type abort to stop the bot)" text_dividend=value
		setVar --name "${dividend_acquired}" --value True
		onError --label get_user_input_for_dividend_exception_handler
		convertStringToNumber --text "${text_dividend}" --allowleadingsign  --allowdecimalpoint  --allowthousands  num_dividend=value
	endWhile
endSub
beginSub --name get_user_input_for_divisor
// Prompts user for divisor input until acquired successfuly or user aborts.
	while --left "${divisor_acquired}" --operator "Is_True" --negate
		inputBox --title "The divisor" --prompt "Enter the divisor (type abort to stop the bot)" text_divisor=value
		setVar --name "${divisor_acquired}" --value True
		onError --label get_user_input_for_divisor_exception_handler
		convertStringToNumber --text "${text_divisor}" --allowleadingsign  --allowdecimalpoint  --allowthousands  num_divisor=value
	endWhile
endSub
beginSub --name get_user_input_for_dividend_exception_handler
// Exception handler subroutine for the get_user_input_for_dividend subroutine.
// Abort if user requests or warn user about invalid input.
	if --left "${text_dividend}" --operator "Matches" --right "(?i)^abort"
		logMessage --message "User wants to abort." --type "Info"
		stopExecution --current
	else
		messageBox --title "Invalid input" --text "Please, enter a valid number!" --icon "Error" --buttons "OK" --defaultbutton "FirstButton"
		setVar --name "${dividend_acquired}" --value False
		recover
	endIf
endSub
beginSub --name get_user_input_for_divisor_exception_handler
// Exception handler subroutine for the get_user_input_for_divisor subroutine.
// Abort if user requests or warn user about invalid input.
	if --left "${text_divisor}" --operator "Matches" --right "(?i)^abort"
		logMessage --message "User wants to abort." --type "Info"
		stopExecution --current
	else
		messageBox --title "Invalid input" --text "Please, enter a valid number!" --icon "Error" --buttons "OK" --defaultbutton "FirstButton"
		setVar --name "${divisor_acquired}" --value False
		recover
	endIf
endSub
beginSub --name evaluate
// Evaluate division. onError watches for unexpected behaviour.
	onError --label evaluate_exception_handler
	evaluate --expression "${num_dividend} / ${num_divisor}" quotient=value
endSub
beginSub --name evaluate_exception_handler
// Display error message and stop.
	messageBox --title "Division went wrong!" --text "${wdg:error.Message}" --icon "Error" --buttons "OK" --defaultbutton "FirstButton"
	stopExecution --current
endSub

You can use Handle Error (onError) on specific subroutines to handle known errors within that scope. Another possibility is to validate the user input:

defVar --name text_dividend --type String
defVar --name text_divisor --type String
defVar --name num_dividend --type Numeric
defVar --name num_divisor --type Numeric
defVar --name quotient --type Numeric
defVar --name valid_input --type Boolean
defVar --name user_input --type String
// Perform division of dividend by divisor and show quotient.

goSub --label get_user_input_for_dividend
goSub --label get_user_input_for_divisor
evaluate --expression "${num_dividend} / ${num_divisor}" quotient=value
messageBox --title "The quotient" --text "${num_dividend} / ${num_divisor} = ${quotient}" --icon "Information" --buttons "OK" --defaultbutton "FirstButton"
beginSub --name get_user_input_for_dividend
// Prompt user for dividend until valid input or user wants to abort.
	setVar --name "${valid_input}" --value False
	while --left "${valid_input}" --operator "Is_True" --negate
		inputBox --title "The dividend" --prompt "Enter the dividend (use . for decimals). This ignores commas. Type abort to end bot." text_dividend=value
		replaceText --texttoparse "${text_dividend}" --textpattern "," text_dividend=value
		if --left "${text_dividend}" --operator "Matches" --right "(?i)^abort"
			goSub --label abort_execution
		else
			goSub --label validate_user_input --assignments "${user_input}=${text_dividend}"
			gosubIf --label warn_invalid_input --left "${valid_input}" --operator "Is_True" --negate
		endIf
	endWhile
	convertStringToNumber --text "${text_dividend}" --allowleadingsign  --allowdecimalpoint  --allowthousands  num_dividend=value
endSub
beginSub --name get_user_input_for_divisor
// Prompt user for divisor until valid input or user wants to abort.
	setVar --name "${valid_input}" --value False
	while --left "${valid_input}" --operator "Is_True" --negate
		inputBox --title "The divisor" --prompt "Enter the divisor (use . for decimals).  This ignores commas. Type abort to end bot." text_divisor=value
		replaceText --texttoparse "${text_divisor}" --textpattern "," text_divisor=value
		if --left "${text_divisor}" --operator "Matches" --right "(?i)^abort"
			goSub --label abort_execution
		else
			goSub --label validate_user_input --assignments "${user_input}=${text_divisor}"
			gosubIf --label warn_invalid_input --left "${valid_input}" --operator "Is_True" --negate
		endIf
	endWhile
	convertStringToNumber --text "${text_divisor}" --allowleadingsign  --allowdecimalpoint  --allowthousands  num_divisor=value
	if --left "${num_divisor}" --operator "Equal_To" --right 0
	// Handle when divisor is 0.
		messageBox --title "Invalid input" --text "Divisor can/'t be 0." --icon "Warning" --buttons "OK" --defaultbutton "FirstButton"
		goSub --label get_user_input_for_divisor
	endIf
endSub
beginSub --name validate_user_input
// Validade user input.
// User input must be a valid number with decimals separated by point.
	replaceText --texttoparse "${user_input}" --textpattern "," user_input=value
	isMatch --text "${user_input}" --regexPattern "^//d+(?:.?//d+)?$" --regexOptions "0" valid_input=value
endSub
beginSub --name abort_execution
// Log and abort execution.
	logMessage --message "User wants to abort." --type "Info"
	stopExecution --current
endSub
beginSub --name warn_invalid_input
// Warn when input is invalid.
	messageBox --title "Invalid input" --text "Please, enter a valid number (use . for decimals)." --icon "Warning" --buttons "OK" --defaultbutton "FirstButton"
endSub

You can validate known exceptions with flow control conditionals. This type of validation makes it easier for you to create specific exception handling logic, but it can make the script grow in size if there are many possible exception events.

The success output parameter

Some commands in IBM Robotic Process Automation have an output parameter called success. This output parameter returns a boolean representing the command's success in doing its task. You can validate this output parameter to handle known exception events in your script by creating alternative conditional flows.