Blog / Technical Guides
Apps Script onEdit Trigger Not Working: 7 Causes and Fixes
By Keyona Meeks, Founder, ReRev Labs · Oct 31, 2026 · 8 min read
The short answer: An
onEditfunction that does not run usually has one of seven causes. The function name is wrong. The script is not attached to the spreadsheet. The file is open in view or comment mode. The change was made by a script or an API, not by a person. The code needs permission to send email or touch another file, which a simple trigger cannot do. The code runs past 30 seconds. Or you ran it by hand from the editor, where there is no edit event. Add a four-line logging function first to see whether the trigger fires at all, then work down the list.
By the end of this post, you'll be able to:
- Tell whether your
onEditfires, in under two minutes. - Name the seven usual causes and the fix for each.
- Switch from a simple trigger to an installable trigger when you need permission.
- Know which fixes I confirmed in Google's docs and which are my reading.
You wrote a function called onEdit. You change a cell. Nothing happens. No error, no email, no log line. This is common, and it is almost never a bug in the logic. It is a rule about when Google runs the function. This post follows Google's trigger documentation, and says where I could not confirm something. I read those pages through a summarizing tool, not word for word, so check the quoted lines against the pages when you open them.
If you are new to Apps Script, read what Google Apps Script is first.
How do you tell whether onEdit fires at all?
Test the trigger before you test your code. Paste the first function below into the Apps Script editor of the spreadsheet, save, then edit any cell by hand in the sheet. A new tab called Trigger log should appear with one row per edit. If it does, the trigger works and the problem is in your own code. If it does not, work through the causes below.
// Step 1: a simple trigger that only writes to a 'Trigger log' tab. If it logs, onEdit works.
function onEdit(e) {
if (!e || !e.range) return; // running it by hand gives no event object
const ss = SpreadsheetApp.getActive();
let log = ss.getSheetByName('Trigger log');
if (!log) log = ss.insertSheet('Trigger log');
if (e.range.getSheet().getName() === 'Trigger log') return; // do not log our own log
log.appendRow([new Date(), e.range.getSheet().getName(), e.range.getA1Notation(), String(e.value)]);
}
// Step 2: the same idea as an installable trigger, for work that needs permission (email, other files).
// Run setupInstallableEdit once. Then delete the simple onEdit above so the work does not run twice.
function handleEdit(e) {
if (!e || !e.range) return;
const sheet = e.range.getSheet();
if (sheet.getName() !== 'Orders') return; // change to your tab
if (e.range.getColumn() !== 5) return; // change to the column you watch
MailApp.sendEmail(Session.getEffectiveUser().getEmail(),
'Edit in Orders', 'Cell ' + e.range.getA1Notation() + ' changed to ' + e.value);
}
function setupInstallableEdit() {
const ss = SpreadsheetApp.getActive();
ScriptApp.getProjectTriggers().forEach(function (t) {
if (t.getHandlerFunction() === 'handleEdit') ScriptApp.deleteTrigger(t);
});
ScriptApp.newTrigger('handleEdit').forSpreadsheet(ss).onEdit().create();
}
The second half of that code is for cause 5. Ignore it for now.
Is the function name exactly right?
Google reserves certain function names for simple triggers. The trigger page lists onEdit(e) as one, and says it "runs when a user changes a value in a spreadsheet." Source: Simple Triggers, checked October 30, 2026. JavaScript is case sensitive, so onedit, OnEdit and on_edit are different names. Rename the function to onEdit and save.
Is the script attached to the spreadsheet?
A simple trigger only works for a script that is attached to a file. Google's page says "The script must be bound to a Google Sheets, Slides, Docs, or Forms file." Source: Simple Triggers, checked October 30, 2026. A project created on its own at script.google.com is not attached. The fix is to open the spreadsheet and choose Extensions, then Apps Script, and put the code there.
Is the file open in view or comment mode?
Google's page says simple triggers "don't run if a file is opened in read-only (view or comment) mode." Source: Simple Triggers, checked October 30, 2026. If a teammate has view or comment access, their edits are not edits to the sheet at all, and your function does not run for them. Give them edit access, or test with an account that can edit.
Was the change made by a script or an API?
This one catches people most. The same page says "Script executions and API requests don't cause triggers to run," and gives the example that calling Range.setValue() does not fire onEdit. Source: Simple Triggers, checked October 30, 2026. The installable triggers page repeats the line. Source: Installable Triggers, checked October 30, 2026.
What this means for you:
- If one script writes a cell and you expect
onEditto react, it will not. Call your function directly from the first script instead. - If another tool writes to your sheet through Google's API, that is an API request. In my search I saw forum threads from people using other apps to write into a sheet who said the trigger did not fire. I did not read or verify them, so treat that as a lead, not a finding.
- A person typing in the sheet is the case that works.
Does the code need permission?
A simple trigger cannot ask for permission. Google's page says simple triggers "can't access services that require authorization," and gives the example that a simple trigger can't send email through Gmail. Source: Simple Triggers, checked October 30, 2026. It also says they can modify the file they are bound to but can't access other files.
If your onEdit sends email, writes to another spreadsheet or reads from Drive, it will quietly do nothing as a simple trigger. The fix is an installable trigger. Google says "Installable triggers, however, offer more flexibility than simple triggers," and that they can call services that require authorization. Source: Installable Triggers, checked October 30, 2026.
To switch:
- Rename your function to something other than
onEdit, for examplehandleEdit, so the simple trigger no longer runs it. If both exist, the work can run twice. - Run
setupInstallableEditfrom the code above once. Google asks you to allow the script. Read the list. Approve it only if you agree. - Edit a cell in the tab and column you set in
handleEdit. In the example, it emails you.
The example handleEdit only emails the person who installed the trigger. Change the tab name and the column number to match your sheet.
Does the code run longer than 30 seconds?
Google's page says simple triggers "can't run for longer than 30 seconds." Source: Simple Triggers, checked October 30, 2026. If your function loops over thousands of rows or calls slow services, it may be stopped before it finishes. Shorten the work: process only the edited row, which you can read from e.range. The installable triggers page says installable triggers are "subject to Apps Script trigger quota limits" and does not list a number in the part I read, so check Google's quotas page for the current limits: Quotas for Google Services.
Did you run onEdit by hand?
If you click Run on onEdit in the editor, there was no edit, so there is no event object. The parameter e is undefined and any line that reads e.range fails. This is my reading of how JavaScript works, not a line from Google's page. The test function above returns early when e is missing so it does not fail. To test your own code, edit a cell in the sheet and check the result, or write a small test function that passes in a fake event.
What if it still does not work?
- Check the account. An installable trigger runs as the account that created it. Google's installable triggers page says they "always run under the account of the person who created them." If that account lost access to the sheet, it fails. Source: Installable Triggers, checked October 30, 2026.
- Check you edited the right tab and column. Your own code may be returning early.
- Look for two triggers. A simple
onEditand an installable trigger that run the same work can double up. - Do not trust one test. Edit three different cells and look at the log each time.
Where does an LLM fit in this?
An LLM can help read a trigger error or suggest where your code might exit early. It cannot see your Google account, your sharing settings or which account created the trigger. A person should check those. The checks in this post are rules: is the name right, is the script bound, who has edit access. My stance: AI writes the code, plain automation runs it, and an LLM shows up only where the input is messy and a person checks the result.
Where this has limits
- I read Google's pages through a summarizing tool. The quoted lines should be checked against the live pages.
- Not run in a live account. I tested the example code with a mock harness (8 of 8 checks passed). I did not run it in Google.
- The manual-run cause is my reading of JavaScript. It is not from Google's page.
- The forum threads are unverified leads.
- Docs change. Google's pages are as of October 30, 2026.
- Simple and installable behavior can differ in details I did not test.
If a sheet automation is running part of your business, see our AI-powered operations work or tell us about it on /letstalk. Bring the script, a copy of the sheet with fake data and what it should do. Do not send passwords or login details.
Frequently asked questions
Why is my onEdit trigger not working?
The usual causes are a wrong function name, a script that is not attached to the spreadsheet, a file opened in view mode, an edit made by a script, code that needs permission, a run longer than 30 seconds, or running the function by hand.
Why doesn't onEdit run when a script changes a cell?
Google says script executions and API requests don't cause triggers to run. Call your function from the first script instead.
Can onEdit send email?
Not as a simple trigger. Google says simple triggers can't access services that require authorization. Use an installable trigger.
What is the difference between a simple and an installable trigger?
A simple trigger runs from a reserved function name and has limits. An installable trigger is created with a setup step, runs under the account that created it, and can call services that need authorization.
Why does onEdit work for me but not for my teammate?
Their access may be view or comment only, and simple triggers don't run in read-only mode. Or the work needs permission they have not granted.
Do I need to know how to code?
You need to paste a function and run one setup step. An AI tool can help you adjust the tab and column. Test on a copy.
Read next: Send an email when a cell changes is the working onEdit build to compare against, run a script on a schedule covers the trigger that does not depend on edits, and the unverified app warning explains the screen that scares people the first time.