28

When running a google apps script from a google spreadsheet, if one of the google apis is used incorrectly a red "butterbar" error is shown at the top of the spreadsheet. This message usually contains info that is useful to the script developer (an error message from a google api, e.g. "The coordinates or dimensions of the range are invalid.") but not necessarily to the spreadsheet user (a real world translation of what they can do to resolve it).

I searched through the UiApp api documentation but didn't see a way of customizing this message. Is it possible to throw your own error message?

Ralf Haring
  • 1,253
  • 1
  • 10
  • 18

3 Answers3

50

As with any javascript, you can use:

try {
  ...
}
catch (error) {
  throw new Error( "More meaningful error." );
}

There are numerous examples of this in use, even if the questions aren't exactly yours.

My personal opinion is that it's best if you check the input to your function and throw errors on that (like this answer), rather than catching the errors from service calls. An appropriate time to use try..catch would be when you have no practical way to validate parameters, as in this answer.

d-_-b
  • 21,536
  • 40
  • 150
  • 256
Mogsdad
  • 44,709
  • 21
  • 151
  • 275
  • Thanks! I didn't know the custom exception would supercede the butterbar text, which is basically exactly what I wanted. As you said, a check beforehand to validate the params passed to the api is exactly what I was planning to do. – Ralf Haring Jun 19 '13 at 01:54
  • 1
    @Mogsdad, this is very helpful indeed, but for the functions initiated on the server. However if the same function is called with google.script.run, the thrown error gets logged in the console. Is there a way to get around this and still display the message in the butterbar? – chibis Jun 25 '14 at 21:12
  • @chibis, when a script is invoked via google.script.run it is given its own execution instance. Here's what I think, without trying it... The "butterbar" is part of the UI presented to a user of the script or container, which is yet another execution instance, and not accessible to the google.script.run instance. Still, that sounds like it should be a question on its own, so go ahead and ask it! – Mogsdad Jun 26 '14 at 12:35
  • This indeed answers the question, but just for future reference: when using this with the sheets APIs (a.k.a. "Deploy as web app"), Google will still return 200 OK, with the custom error in some HTML response. See [Allow scripts to send response codes other than 200](https://issuetracker.google.com/issues/36759757) in Google's issue tracker. – Arjan Sep 18 '19 at 12:43
  • Flipped closing squiggly bracket at bottom of example code. – user66001 May 29 '20 at 01:16
  • @d-_-b You vandalized this answer, probably by accident. Please be more careful with your edits. – Mogsdad Feb 04 '22 at 14:33
4

Here is the best way to pass data from your script into your error message. First setup a global variable object to store your data that you need for the error handling. Then store data to this object in each function's try{} section. Finally in catch(e) call an errHandler function that will pass the error data object. See the following code: code.gs.

var onErrObj = {}
function myFunction(){

 try{
  // function code goes here;
  // add more elements to onErrObj as desired;
 }catch(e){
      onErrObj['data1'] = 'someData';
      onErrObj['data'] = 'some Other Data';
      errHandler(e,'myFunction');
 }

 function errHandler(e,strFunc){
      var message = e.message+'\n in file: '+e.fileName+' on line: '+e.lineNumber;
      var sendto = 'yourname@youremail.com';
      var subject = 'My App encountered an error occured in '+strFunc;
      var errProps = JSON.stringify(this.onError);
      message = subject+'\n'+message+'\n onError: '+errProps;
      GmailApp.sendEmail(sendto, subject, message); 
}
0

You can try to have a look to the Base class that gives you the possibility to add alert box or other dialogs to interact with the user of your application if it is bound to a Spreadsheet (for example msgBox()). For a DocumentApp use the Ui class to interact with its interface.

I never tried but if you use a try...catch structure with a throw statement it can also work.

Cheers

Nicolas