Skip to content
// field note2026 · Jul · Updated Sep 136 min read

Why your Apps Script trigger did not fire: a reproducible diagnostic.

Start with what changed the Sheet. More permissions cannot turn a script or API write into a human edit event.

First separate a missing event from a failed handler

Updated September 13, 2026. A row appears, but the automation does nothing. Check the project execution history: did the handler run and fail, or was no execution recorded? Those observations need different fixes. Selecting a handler and pressing Run in the editor does not supply a trigger event.

Google documents that script executions and API requests do not activate these spreadsheet triggers. Replacing simple onEdit with an installable edit or change trigger does not bridge that gap. For an integration that writes rows, arrange an explicit processing call after the write, or use a scheduled scan with stored progress and duplicate protection.

Get the recorder and establish a positive control

Use a new disposable spreadsheet containing only fictional data, with a tab named TriggerProbe. Open Extensions → Apps Script and paste the downloadable probe into its empty bound project. Save it. Do not paste it into an existing production project with another onEdit function.

In the spreadsheet, type ui-probe into TriggerProbe!A1. This is the human-edit positive control. Look for an onEdit execution and a simple-edit record. Record the action time, handler, status and log visibility. A missing log is not proof that the event could never fire: check the correct project, save state, errors and logging visibility first.

Probe v1 has passed local fixtures for event formatting, privacy and guarded writes. We have not measured its Google-hosted event delivery. This is a reproducible test procedure with documented expectations, not a published Google execution benchmark.

Compare installable edit, change and form-submit events

Using one installer account, open the project trigger panel and add three triggers, each with event source From spreadsheet: probeInstalledEdit → On edit; probeChange → On change; probeSheetSubmit → On form submit. Review the consent screen before authorizing. Do not install another trigger on the reserved onEdit function. Confirm one of each named handler in the list.

Change A1 by hand again. Inspect the installed-edit record separately from simple-edit. For the change handler, record the actual change_type; do not assume that a change event provides an edited range. To test a form submission, link a disposable Google Form to this same spreadsheet and submit fictional data through its respondent UI. Inspect sheet-form-submit independently of the edit test.

The Sheets form-submit event and the Forms form-submit event are different shapes: the former exposes range, values and namedValues; the latter exposes response. This recorder targets the spreadsheet side. A handler written for the wrong shape can run and then fail.

Run the script-write case without faking an event

Select writeTriggerProbe and run it once. It checks the dedicated tab and refuses formulas or unrelated A1 contents, then writes a timestamped script-probe marker and flushes. Record script-write-completed as proof that the writer finished, not as a trigger observation. The downloaded handlers never call one another to manufacture delivery.

For this case, the documented expectation is no edit, change or form-submit trigger caused by setValue. Observe a fixed interval, such as two minutes, and retain the start/end times and any actual executions. That interval is your measurement window, not a Google delivery guarantee. Repeat the human-edit control separately if logging is unclear.

Keep the API-write case separate

If you already have an authorized Sheets API client, use spreadsheets.values.update with valueInputOption=RAW to write the literal api-probe to TriggerProbe!A1 in the same disposable spreadsheet. Save the successful API response and action time privately, then inspect the same observation window. A successful write is not evidence that a trigger ran.

If API authorization is unavailable, mark this case not run. Running writeTriggerProbe again is not an API test. Never publish an access token, spreadsheet ID, form answers or an unredacted execution screenshot as a diagnostic result.

{
  "range": "TriggerProbe!A1",
  "majorDimension": "ROWS",
  "values": [["api-probe"]]
}

Read metadata, then remove the experiment

The recorder emits only the handler label, timestamp, recognized auth/change enums and booleans describing the event shape. It omits cell contents, form answers, user identity and document IDs. Google stores execution logs; the probe makes no network call to bulldo.gs and sends no email. Keep even these diagnostic logs private unless you deliberately share a redacted result.

Remove the three installed triggers from the account that created them. Confirm they are gone, then delete the probe code too: removing installable triggers does not disable a saved simple onEdit. Trash the disposable Form and Sheet when finished. Another account can have its own triggers, so one account’s empty list is not a universal inventory.

Choose the fix that matches the writer

For a human-edit handler that needs authorized services, an installable edit trigger may be appropriate; it executes under its creator’s account. For a linked Form UI submission, use the matching form-submit handler and event shape. For script or API writes, explicitly invoke processing from the integration or scan on a schedule. Inspect permissions and test the changed path before using real data.

If you choose a schedule, remember that time-driven triggers are installable triggers and their timing can be approximate. Design for safe repeated processing rather than inferring exactly-once delivery from an empty log. This diagnostic does not promise trigger latency or test time-driven execution.

FAQ

Will an installable onChange detect rows written by the Sheets API?
Google documents that script executions and API requests do not activate these triggers. Use an explicit processing call or a scheduled scan with progress and duplicate protection.
Why does the probe reject Run on an event handler?
An editor invocation has no trigger event. Perform the actual edit or Form submission, then inspect that execution. Only writeTriggerProbe is intended as the manual script-write case.
Are these measured Google results?
No. Probe v1 has local fixture checks; its Google-hosted event delivery is unmeasured. The guide distinguishes documented expectations, actual observations and cases not run.

Skip the boilerplate.

Describe the automation and Gnaw drafts an Apps Script starting point. Review its permissions and test with sample data before using it. Free, no login.