catching "generic" GAS server errors

85 views
Skip to first unread message

Edward Wu

unread,
Apr 11, 2024, 12:41:00 PMApr 11
to google-apps-sc...@googlegroups.com
Every once in a while, we get error email notifications (for functions that run on triggers) that appear to have nothing to do with the script/function itself, but seem to be some sort of server problem.
These are all scripts that run perfectly fine e.g. 99% of the time, so I can only assume that the problem is happening with the GAS server that's running them.


Example 1, where YYYYYYYYYYYYY is the ID of the Google Sheet container:

Your script, XXXXXXXXXX, has recently failed to finish successfully. A summary of the failure(s) is shown below. To configure the triggers for this script, or change your setting for receiving future failure notifications, click here.

StartFunctionError MessageTriggerEnd
4/10/24, 6:37:45 PM Pacific Daylight TimeXXXXXXXXXXXService Spreadsheets failed while accessing document with id YYYYYYYYYYYYYtime-based4/10/24, 6:37:57 PM Pacific Daylight Time


Example 2:

Your script, XXXXXXXXXX, has recently failed to finish successfully. A summary of the failure(s) is shown below. To configure the triggers for this script, or change your setting for receiving future failure notifications, click here.

StartFunctionError MessageTriggerEnd
2024-04-11 06:02:30 Pacific Daylight TimeXXXXXXXXWe're sorry, the JavaScript engine reported an unexpected error. Error code INTERNAL.time-based2024-04-11 06:05:28 Pacific Daylight Time



Is there any way to do a try/catch or any other sort of error handling to try to deal with these when/if they come up?

Matías Pco.

unread,
Apr 12, 2024, 1:20:13 PMApr 12
to Google Apps Script Community
Example 1: Normalmente se genera ese error si configuras el activador desde la cuenta del usuario A y después le cambias el permiso que tiene el usuario A en el Documento que intenta conectar el Script de Editor a Lector/comentador.

Example 2: Normalmente ocurre cuando usas Activadores simples e intentas realizar operaciones profundas dentro del mismo activador. Para operaciones largas y/o profundas se debe usar los Activadores instalables. 

Fabrice Faucheux

unread,
Apr 13, 2024, 11:03:36 AMApr 13
to Google Apps Script Community
Hi,

Dealing with intermittent server errors in Google Apps Script, especially those occurring due to issues on Google's side, can be challenging. The errors you've described seem to be out of your control, typically related to the server or the environment rather than your script's logic. However, you can implement some strategies in your script to handle these errors more gracefully and retry the operations when they fail.

Strategies for Error Handling and Retries

1. Basic Try/Catch Block: Start by wrapping your potentially error-prone code in `try/catch` blocks. This allows you to catch exceptions when they occur and handle them, possibly by logging or retrying the operation.

2. Exponential Backoff for Retries: For transient server errors, implementing a retry mechanism with exponential backoff can be effective. This means if an operation fails, the script will wait for a brief period before trying again, with the wait time increasing exponentially with each failure, up to a maximum number of retries.

3. Logging Errors: Use logging to record errors and their context. This can help in diagnosing issues over time or identifying patterns in failures.

4. Notification System: Enhance your error notifications beyond the default emails from Google. For instance, your script can send detailed error reports through emails or log entries to a Google Sheet or another logging service.

Example Implementation in Google Apps Script

Here’s a basic example showing how to implement these strategies in a script that might be prone to intermittent errors:

function retryFunction() {
  var maxRetries = 5;
  var retryCount = 0;
  var success = false;

  while (retryCount < maxRetries && !success) {
    try {
      // Replace the next line with the code you want to retry
      var result = SpreadsheetApp.openById('YYYYYYYYYYYYY').getSheets();
      // If the above line executes without throwing an error, set success to true
      success = true;
      return result;  // or handle the result as needed
    } catch (e) {
      // Log the error
      Logger.log('Attempt ' + (retryCount + 1) + ' failed with error: ' + e);
      retryCount++;
      Utilities.sleep(Math.pow(2, retryCount) * 1000);  // Exponential backoff
    }
  }

  if (!success) {
    // Handle the final failure case after retries are exhausted
    Logger.log('Failed after ' + maxRetries + ' attempts');
    // Optional: send an email notification or record this event in a spreadsheet
  }
}

Points to Note
  • Exponential Backoff: The `Utilities.sleep()` function is used to pause the script execution between retries. The sleep time increases exponentially, which is a recommended practice to prevent overwhelming the server with frequent requests after a failure.
  • Failure Handling: After the maximum number of retries, you might want to implement a notification or logging system that informs you of the persistent issue so you can investigate further.
  • Testing: Ensure you test this in a controlled environment to see how it behaves during failures. This can help fine-tune the number of retries and the backoff algorithm.
Implementing these strategies won't prevent server-side errors but can make your scripts more robust and resilient, reducing the impact of intermittent issues on your automated processes.

Fabrice

Edward Wu

unread,
Apr 16, 2024, 6:01:29 PMApr 16
to google-apps-sc...@googlegroups.com
Thank you, Fabrice.

The problem is that it seems like the function doesn't even get that far. I do have the parts of the functions that access Google Sheets wrapped in try/catch. But they don't seem to be able to catch the *server* errors because it doesn't seem to get that far.

And the errors are so intermittent that it doesn't seem worthwhile to do convoluted workarounds like "run at 1am, then run again at 2am to see if the 1am run worked".


--
You received this message because you are subscribed to the Google Groups "Google Apps Script Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-apps-script-c...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-apps-script-community/570937f7-c24e-4904-85fe-3d739b58fa36n%40googlegroups.com.

Edward Wu

unread,
Apr 30, 2024, 6:03:48 PMApr 30
to google-apps-sc...@googlegroups.com
I'm running into a really weird situation in Google Apps Script. It's easier to show than to explain:

Here's a sample function:

function runExports(isManualRun) {
  isManualRun = isManualRun ? isManualRun : false;
  Logger.log(`isManualRun: ${isManualRun}`);
}

This is pretty straightforward. I expect that when it runs directly, isManualRun should be false, since there was no value passed to it.
And if I do manually run it directly, isManualRun shows false as expected.

But if the function runs in a trigger, it's showing isManualRun = [object Object]

I've triple-checked and isManualRun is not defined globally anywhere.

I even tried changing the variable name to someVar and get the same results, so it's not because I accidentally defined it elsewhere.

I found someone else with the same issue: https://stackoverflow.com/questions/59014291/why-is-value-not-undefined-for-function-parameter-when-executed-by-time-driven-t

This is bizarre. I can figure out workarounds, but I'm more curious: *why* does this happen? Is this expected behavior? Is there a "real" fix vs doing workarounds like checking for the variable's typeof vs its expected type?


Edward Wu

unread,
Apr 30, 2024, 6:15:55 PMApr 30
to google-apps-sc...@googlegroups.com
...and this only seems to happen with the *first* passed parameter.

If I try this:

function thisTest(someVar, anotherVar) {
  someVar = someVar ? someVar : false;
  anotherVar = anotherVar ? anotherVar : false;
  Logger.log(`someVar: ${someVar}`);
  Logger.log(`anotherVar: ${anotherVar}`);
}


Running it manually gives me:
3:14:18 PM Info someVar: false
3:14:18 PM Info anotherVar: false

Which is what I expect.

But running it on a trigger gives me:
Apr 30, 2024, 3:12:27 PM Info someVar: [object Object]
Apr 30, 2024, 3:12:27 PM Info anotherVar: false

George Ghanem

unread,
Apr 30, 2024, 11:44:01 PMApr 30
to google-apps-sc...@googlegroups.com
A trigger function when it is invoked is passed the environment variable as to what condition caused the trigger. If a form submission, the env variable would give you the form data, etc..

So yes, this is expected.

Why are you passing it as a parameter if you don't want any value in it? Perhaps it may help if you provide us with more details on what you are trying to do.

--
You received this message because you are subscribed to the Google Groups "Google Apps Script Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-apps-script-c...@googlegroups.com.

Edward Wu

unread,
May 1, 2024, 4:08:32 PMMay 1
to google-apps-sc...@googlegroups.com
Ah, that makes sense. Thank you.

I'm trying to differentiate between different run conditions, and now that I know that this is expected behavior, I know how to deal with it.

Thanks!

George Ghanem

unread,
May 2, 2024, 12:10:45 AMMay 2
to google-apps-sc...@googlegroups.com
You are welcome. Look into the definition of the trigger environment object. It has lots of data to tell you how the trigger occurred which may help your situation.

Reply all
Reply to author
Forward
0 new messages