Service Details
Google Apps Script Blog Topics
Google Apps Script Exception Handling
In this tutorial, we explore exception handling in Google Apps Script—an often overlooked but essential aspect of writing resilient code. While many developers focus on getting their scripts to work, handling unexpected errors gracefully is what separates a quick fix from a robust solution. By implementing structured error handling, you can prevent silent failures, surface meaningful messages, and ensure your apps behave predictably even when things go wrong. Let’s dive into practical techniques that make your scripts smarter, safer, and easier to maintain.
Exceptions are exactly what the name implies—something unexpected has occurred. In older programming languages, error handling often relied on checking global variables and using simple if statements to detect and respond to failures. While functional, this approach blurred the line between application logic and error management. Modern programming languages, including Google Apps Script, offer dedicated constructs like try, catch, and finally to handle exceptions more cleanly and predictably. This separation allows developers to write more robust, maintainable code. Some exceptions are recoverable—for example, a timeout during an API call—while others may require manual intervention, such as when a referenced file has been deleted. Understanding how and when to handle these scenarios is key to building resilient applications.
Now let's look at a simple exception handler, illustrated in Sample 1. In this example, an exception is triggered when the script attempts to access a null object—something that often happens when a resource isn't properly initialized or a lookup fails. Instead of letting the script crash silently or halt execution, we wrap the risky operation in a try...catch block. This allows us to intercept the error, log a meaningful message, and optionally notify the user or take corrective action. Exception handling like this adds a layer of resilience to your code and helps you maintain control even when things don't go as planned.
As you can see in the example, the exception is an object instance of a class—just like any other in JavaScript. This means we can test for the type of exception by checking its constructor or using instanceof, allowing us to tailor our response based on the specific error type. It’s good practice to define custom exception classes that are closely tied to your application’s logic or domain. For example, you might create a DataValidationError or MissingConfigError class to represent specific failure modes. This approach not only improves clarity but also makes your error handling more modular and maintainable, especially in larger Apps Script projects.
function TestException()
{
try
{
let data = null;
data.property = "value"; //This will throw a TypeError
}
catch(ex)
{
//Handle the exception:
if (ex instanceof TypeError)
Logger.log("TypeError occurred: " + ex.message)
else if (ex instanceof ReferenceError)
Logger.log("ReferenceError occurred: " + ex.message);
else
Logger.log("An unexpected error occurred: " + ex.message);
}
}
Sample 1: Exception handling
As Sample 2 shows, you can throw a custom exception when something goes wrong in your code—giving you full control over how errors are defined and surfaced. This allows you to create meaningful exception types that reflect the context of your application, such as InvalidUserInput or MissingConfiguration. Once thrown, these exceptions should be handled appropriately using try...catch blocks, where you can log the error, notify the user, or trigger fallback logic.
function ValidateRating(aRating)
{
if (typeof aRating !== "number" || aRating < 1 || aRating > 5)
throw "Invalid score: Score must be a number between 1 and 5.";
}
function TestRating()
{
ValidateRating(1);
ValidateRating(10);
}
Sample 2: Custom exception
Let's look at Sample 3 to see how to implement error recovery in a real-world scenario. The function begins by simulating an error condition—attempting to access an invalid endpoint. When this fails, the exception handler steps in to correct the endpoint and retry the operation. This mirrors what might happen in production if, for example, a server is temporarily down or misconfigured. To manage retries, we use a loop—but to prevent runaway execution, we cap the number of attempts with a counter.
Another important and often misunderstood construct is try...finally. This ensures that the code inside the finally block always executes, regardless of whether an exception was thrown. In our example, the decrement of the retry counter is placed inside finally to guarantee it runs even if the request fails. This is critical for maintaining control flow and avoiding infinite loops. However, be cautious: if an exception is raised inside the finally block and there’s no surrounding catch, it will go unhandled. So be very mindful when writing your finally logic—it's powerful, but it demands precision.
function Recover()
{
let url = "http://api.apis.guru/v2/list.jsonX";//Invalid end point
let options = {
'method' : 'get',
'muteHttpExceptions': true
};
RetryCount = 5;
while (RetryCount > 0)
{
try
{
try
{
var response = UrlFetchApp.fetch(url);
var responseCode = response.getResponseCode();
var responseBody = response.getContentText();
if (responseCode == 200)
Logger.log("Successful response: " + responseBody);
else
{
Logger.log("Error response code: " + responseCode);
Logger.log("Error response body: " + responseBody);
}
}
finally
{
RetryCount--;
}
}
catch (e)
{
Logger.log("Request failed: " + e.message);
url = "http://api.apis.guru/v2/list.json";//Valid end point
}
}
}
Sample 3: Exception Recovery
This concludes our tutorial on error handling in Google Apps Script. Throughout this guide, we explored the importance of anticipating and managing unexpected conditions—whether it's a null object, a failed API call, or a misconfigured endpoint. We covered the basics of try...catch for intercepting errors, the use of custom exception classes for clarity and modularity, and the powerful role of finally in ensuring cleanup and control flow. We also looked at real-world recovery strategies, like retry loops with safeguards, and emphasized the need for thoughtful exception design that separates application logic from error handling. By applying these principles, you’ll write more resilient, maintainable scripts that behave predictably—even when things go wrong.
Updated: 6 September 2025