n8n Gmail Trigger Not Working? Fixes for Missed, Duplicate and Multiple Emails
"Gmail Trigger not working" is one of the most repeated n8n questions. The forum has threads on every flavor: it only runs when I execute it manually, it fails most of the time, it misses emails that arrive together, it skips messages that arrive close together and it fires several times for the same email. Most of these come down to one fact: the Gmail Trigger is a polling trigger, not a push notification. Once you know how a poll works, the fixes are short.
Gmail AI Email Assistant (Draft-Only) n8n template. Pay what you want, $0 is fine.
Paid option for bulk jobs: if you log emails to a Google Sheet and run AI over the rows, the Pro Kit adds the Google Sheet header CSV, a 10-minute setup guide and an offline test kit (a local OpenAI, Google Sheets and Gmail mock with the 15-scenario runner), so you can watch the retries and resume work before you use a real API key. The Gmail template on this page stays free.
How the Gmail Trigger actually works
- On each poll (every minute by default, or your Poll Times setting) n8n asks Gmail for messages that match your filters and arrived after the last check.
- The node's Read Status filter defaults to Unread emails only. If you, a phone app or another rule opens the email before the poll runs, it's skipped.
- When several emails match in one poll, they arrive as several items in one execution, not as several executions.
- In recent node versions, Max Emails per Poll (default 10, max 50) caps each poll and queues the rest for the next one (n8n docs: Gmail Trigger).
- Clicking Test / Fetch Test Event returns only the latest matching email, even an old one. That's why "it works when I test it" proves the credential, not the live behavior.
Symptom 1: it only works when I click Test
A manual test runs the poll once, right now. Live polling only happens when the workflow is active (published, on newer versions). Check these in order:
- The workflow is active, and you're looking at Executions, not the editor canvas. Live runs don't appear on the canvas.
- The test email is unread and arrived after you activated the workflow. Old emails won't fire a live poll.
- Your filters (Label, Search, Sender) actually match the email. Paste the Search value into Gmail's own search box; if Gmail finds nothing, n8n won't either.
- Self-hosted: the server can reach Google. In this solved thread polls failed with
ETIMEDOUTbecause the server tried IPv6 first; the fix wasNODE_OPTIONS=--dns-result-order=ipv4firstin the n8n service environment. A quick reachability test iscurl https://www.googleapis.com/gmail/v1/users/me/profile: a 401 response means the network is fine. - A
401 unauthorized_clienterror usually means the Gmail API isn't enabled for your Google Cloud project, or (for service accounts) domain-wide delegation is missing (n8n docs: Gmail common issues). If the error is instead the long "authorization grant ... is invalid, expired, revoked" message, or the trigger stops every 7 days, the stored token has expired: see the n8n Google OAuth invalid_grant guide.
Symptom 2: only one of several emails gets processed
Usually the trigger did fetch them all, and a later node threw away all but the first. Since several emails arrive as several items in one execution, look for:
- Expressions using
.first()or$input.first(), or.all()[0], instead of{{ $json.subject }}or.item. - A node with Settings > Execute Once turned on.
- A Code node in Run Once for All Items mode that returns a single object. Either switch it to Run Once for Each Item, or map over every item:
// Code node, mode: Run Once for All Items
return $input.all().map(item => ({
json: {
id: item.json.id,
threadId: item.json.threadId,
from: item.json.From || item.json.from,
subject: item.json.Subject || item.json.subject,
},
}));
Open the trigger's output in a live execution: if it shows "3 items" and your next node shows "1 item", the loss is downstream, not in Gmail. If emails are really missing at the trigger, check whether they were read before the poll, and whether a burst exceeded Max Emails per Poll on a slow interval. Older n8n versions also had known gaps here (staff reply in this thread), so updating n8n is worth doing first.
Symptom 3: the same email triggers twice
Duplicate runs were a known bug in older versions (see this thread); update n8n before anything else. After that, the usual causes are a test run plus a live run hitting the same email, two active copies of the workflow (common after duplicating or importing one), or two emails in the same thread (a reply plus the original). If you only want one run per conversation, de-duplicate by threadId:
// Code node, mode: Run Once for All Items
const seen = new Set();
return $input.all().filter(item => {
const id = item.json.threadId;
if (seen.has(id)) return false;
seen.add(id);
return true;
});
To also block repeats across executions, add a Remove Duplicates node with the operation Remove Items Processed in Previous Executions, Keep Items Where: Value Is New, and dedupe on {{ $json.id }} (n8n docs: Remove Duplicates; it stores 10,000 values by default).
The pattern that doesn't miss or repeat: a "done" label
The most reliable setup, and what n8n staff suggested in the duplicates thread, is to let a Gmail label track state instead of relying on timing:
- In Gmail, create a label with a simple name, for example
n8n-done. - Schedule Trigger: every 1 to 5 minutes.
- Gmail node: Resource Message, Operation Get Many, Return All on (or a sensible Limit), Filters > Search:
in:inbox -label:n8n-done newer_than:2d. Turn off Simplify if you need the body or headers. - Your processing nodes (AI draft, Sheets row, Slack alert...).
- Gmail node: Resource Message, Operation Add Label, Message ID
{{ $('Get many messages').item.json.id }}(use your Gmail node's name), Label:n8n-done.
Put the label step after the step that does the real work. If the workflow fails halfway, the email has no label and is picked up again on the next run instead of being lost. Because the state lives in Gmail, it doesn't matter whether you read the email on your phone first, and a burst of 20 emails is just 20 items on the next run. The newer_than:2d part keeps the first run from pulling your whole inbox.
Prefer to keep the Gmail Trigger? You can use the same idea with it: set its Search filter to -label:n8n-done and Read Status to Read and unread, and finish the workflow with the same Add Label step.
n8n-done label. If one has no label, that execution failed, and the next run will retry it.Next step: do something useful with each email
Once the trigger is reliable, the n8n Gmail AI agent that drafts replies guide shows how to turn each new email into a reviewed reply draft, and this fix keeps those drafts in the original thread. The ready-made workflow is pay-what-you-want on Gumroad: Gmail AI Email Assistant (Draft-Only) n8n template.
Free: AI Prompt Pack for Wholesalers & Job Seekers
10 copy-paste prompts from our paid packs: seller lead triage, underwriting, objection replies, job fit scoring, honest cover notes and interview prep. Free download (PDF); Gumroad asks for your email so it can send you the file.
Get the free prompt packNo email? Download the PDF directly.
Gmail AI Email Assistant (Draft-Only) n8n template. Pay what you want, $0 is fine.
FAQ
Why does my n8n Gmail Trigger only work when I click Test?
The Gmail Trigger is a polling trigger. A manual test fetches the latest matching email once; live polling only runs when the workflow is active, and by default it only picks up unread emails that arrived after the last check.
Why does the n8n Gmail Trigger miss emails?
Common causes: the email was read before the poll ran (Read Status defaults to unread), a later node only processes the first item when several emails arrive in one execution, or a burst exceeded Max Emails per Poll. A Schedule Trigger plus Gmail Get Many with a done label avoids timing issues.
How do I stop n8n from processing the same Gmail email twice?
Update n8n, make sure only one copy of the workflow is active, and add a label after processing that your search excludes (for example -label:n8n-done). A Remove Duplicates node set to Remove Items Processed in Previous Executions on the message id also blocks repeats.