Nightly jobs that "mostly work" fail quietly until a teammate notices bad data. emailErrorAlert sends you a plain Gmail with the error message, a short stack, and optional context — distinct from sendGmail / sendHtmlEmail marketing helpers.
What you'll need
- A script authorized for Gmail
- An active user identity (container-bound or installed as you)
- Something worth catching (prefer wrapping the real work, not every helper)
How to use this snippet
function emailErrorAlert(subject, err, context) {
var to = Session.getActiveUser().getEmail();
if (!to) throw new Error('emailErrorAlert: no active user email');
var msg = (err && err.message) ? err.message : String(err);
var stack = (err && err.stack) ? String(err.stack).substring(0, 800) : '';
var ctx = '';
if (context != null) {
try {
ctx = JSON.stringify(context).substring(0, 500);
} catch (e) {
ctx = String(context).substring(0, 500);
}
}
var body = [
'Apps Script error alert',
'',
'Message: ' + msg,
stack ? ('Stack:\n' + stack) : '',
ctx ? ('Context: ' + ctx) : '',
'',
'Time: ' + new Date().toISOString()
].filter(Boolean).join('\n');
GmailApp.sendEmail(to, subject || 'Apps Script error', body);
}
Example
function nightlySync() {
try {
var result = syncLeads_(); // your real work
logSheet_('INFO', 'nightlySync ok', result);
} catch (err) {
logSheet_('ERROR', 'nightlySync', err.message);
emailErrorAlert('nightlySync failed', err, {
fn: 'nightlySync',
spreadsheetId: SpreadsheetApp.getActiveSpreadsheet().getId()
});
throw err; // keep the execution red in the dashboard
}
}
Tips:
- Put the function name in
subjectso inbox search stays useful. - Keep
contextsmall (ids, counts) — not full row dumps. - Pair with a Log sheet line so email isn't your only audit trail.
- Time-driven triggers run as the installing user; confirm that mailbox is the one you read.
Happy Coding!
