How to Fix n8n Gmail Trigger ETIMEDOUT on Self-Hosted n8n (Broken IPv6 Route)
Introduction
Your Gmail Trigger workflow was fine for weeks, then it started failing most of the time with a cryptic socket error, even though you changed nothing and curl from the same server reaches Google without complaint. If you self-host n8n on a VPS, this pattern has a single most likely cause: Node.js is trying the IPv6 route to Google’s API, and that route is broken on your server. This tutorial is for self-hosters seeing connect ETIMEDOUT on the Gmail Trigger, and it walks you through proving the IPv6 theory, applying the one-line fix correctly for systemd and Docker installs, and confirming the fix stuck.
Quick answer
Force Node.js to prefer IPv4: set NODE_OPTIONS=--dns-result-order=ipv4first in the n8n process environment, then restart n8n. Systemd installs add it as Environment= in n8n.service; Docker installs add it to the compose environment block.
Evidence: why the trigger fails but curl works
The telltale signature of this bug is asymmetry. A resolved n8n community thread from August 2026 documents a self-hoster whose Gmail Trigger failed “most of the time” while manual curl calls to the same Google API endpoint succeeded every time. Seven replies later, the thread closed as solved with a single environment variable. That asymmetry is exactly what a dead IPv6 route produces: curl and Node.js resolve DNS and order the returned addresses differently, so one tool walks the working IPv4 path while the other repeatedly walks into the dead IPv6 one.
The mechanism is in Node.js itself. The Node.js command-line options documentation defines --dns-result-order as the flag that “sets the default value of order in dns.lookup()”, with verbatim as the default. Under verbatim, Node.js returns the addresses in the order the resolver gave them, and on many VPS resolvers that order puts Google’s AAAA (IPv6) records first. When the server’s IPv6 route is firewalled or blackholed, the TCP connect to port 443 hangs until the socket gives up, and n8n reports connect ETIMEDOUT. It is a socket-layer failure, not an authentication failure, which is why reconnecting your Google credentials never helps. The accepted solution in that community thread makes the diagnostic and the fix explicit: “If this returns 401 (Unauthorized): The network path is open (401 is expected because you aren’t passing a token). If this still times out: Your outbound firewall is blocking port 443 to Google’s IP ranges entirely, and you must request the network admin to whitelist *.googleapis.com.”
A quota check rules out the other suspect. Google’s official Gmail API usage limits grant 1,000,000,000 quota units per day, and the Gmail Trigger’s default poll interval is “Every Minute” per the official Gmail Trigger node documentation, which costs a tiny fraction of that budget. When the trigger fails intermittently rather than always, with ETIMEDOUT rather than a 429 or 401, quota and credentials are both exonerated, and the IPv6 route is the prime suspect. The same environment variable system is documented in the official n8n environment variables reference, which confirms NODE_OPTIONS-style configuration is a supported way to tune the n8n runtime. For the broader picture of n8n self-hosting, our complete n8n self-hosting guide covers install through hardening.
Prerequisites
- Self-hosted n8n 2.x on a Linux VPS, installed via systemd or Docker
- SSH access to the server with sudo rights
- A workflow using the Gmail Trigger node (poll mode, the default)
- The exact error text:
connect ETIMEDOUT <ip>:443in the workflow execution log or journalctl
Step-by-step guide
Step 1: Confirm the signature in the logs
Look at a failed execution in the n8n UI, or query the service journal:
sudo journalctl -u n8n --since "2 days ago" | grep -iE "etimedout|gmail" | head -20
What you want to see is connect ETIMEDOUT followed by an IP address on port 443, repeating across executions. Intermittency is the key: if roughly half or more of the poll cycles fail while some succeed, and the failures name an IP address rather than a hostname, you are looking at address-family flapping between IPv4 and IPv6. A consistent 401 or “Invalid credentials” error means stop here, this guide is not for that problem.
Step 2: Prove it is IPv6 with curl
Run the same HTTPS request forcing each address family separately, exactly as the community solution recommends:
# Force IPv4
curl -4 -v --max-time 15 https://www.googleapis.com/gmail/v1/users/me/profile
A 401 Unauthorized response is the success case here, because it proves the TCP connection and TLS handshake completed (you simply have no token attached). Now try IPv6:
# Force IPv6
curl -6 -v --max-time 15 https://www.googleapis.com/gmail/v1/users/me/profile
If the IPv4 call returns 401 quickly while the IPv6 call hangs until the timeout, you have proven the diagnosis: Google’s AAAA route is broken from this server, and Node.js is picking it up under the default verbatim DNS ordering. If even the IPv4 call times out, the problem is the outbound firewall, not IPv6, and you need the network admin to open port 443 to *.googleapis.com before anything else.
Step 3: Apply the fix on a systemd install
Open your n8n service unit. The file is usually /etc/systemd/system/n8n.service (check your own filename if you customized it):
sudo nano /etc/systemd/system/n8n.service
Add the line inside the [Service] section, next to your other Environment= lines:
[Service]
Environment=N8N_HOST=0.0.0.0
Environment=NODE_OPTIONS=--dns-result-order=ipv4first
ExecStart=/usr/bin/n8n start
The critical step people skip is the daemon-reload. systemd reads unit files once; editing the file without reloading changes nothing:
sudo systemctl daemon-reload
sudo systemctl restart n8n
Step 4: Apply the fix on a Docker install
In your docker-compose.yml, add the variable to the n8n service environment block:
services:
n8n:
image: n8nio/n8n:2.41.7
environment:
- N8N_HOST=0.0.0.0
- NODE_OPTIONS=--dns-result-order=ipv4first
Then recreate the container:
docker compose up -d
Step 5: Verify the variable reached the running process
For systemd, inspect the running unit’s effective environment:
sudo systemctl show n8n | grep NODE_OPTIONS
Expected output:
Environment=NODE_OPTIONS=--dns-result-order=ipv4first
For Docker:
docker exec n8n env | grep NODE_OPTIONS
If the variable does not appear, the restart did not take effect, or you edited a different unit file than the one systemd loaded. Check systemctl status n8n for the loaded unit path.
Step 6: Confirm the trigger recovers
Watch the next several poll cycles of your Gmail Trigger workflow. The official Gmail Trigger documentation notes the default poll interval is every minute, so within five minutes you should see consecutive successful polls in the executions list. Send yourself a test email to confirm an execution fires on the new message. Then run a longer observation: leave the workflow active for 24 hours and check that ETIMEDOUT no longer appears in the journal:
sudo journalctl -u n8n --since "24 hours ago" | grep -c ETIMEDOUT
Zero matches means the fix is holding.
Troubleshooting
1. The variable is set but ETIMEDOUT persists.
First check whether the failures moved from intermittent to constant. Constant failures mean the firewall hypothesis from Step 2 was the real one all along, and you need port 443 opened to Google’s ranges. If failures are still intermittent, confirm you restarted the actual n8n process: sudo systemctl show n8n | grep NODE_OPTIONS must show the variable. Also check for a second n8n process running outside systemd (for example a leftover n8n start in a tmux session) that is executing your workflows instead.
2. curl -4 works but the node still fails with a DNS error.
Some users conflate this bug with a different one: “The DNS server returned an error, perhaps the server is offline.” That is resolution failing entirely, not address-family ordering. For that, test DNS from inside the n8n runtime environment (inside the container for Docker installs, or as the n8n service user for systemd installs), because the container’s resolver can differ from the host’s. Check docker exec n8n nslookup www.googleapis.com for the Docker case.
3. Gmail Trigger fails but the Gmail node (send/read) works. The trigger polls on a timer in the background while manual node executions run fresh, so the intermittent address-family flapping hits the trigger harder. It is also possible the trigger uses a separate long-lived connection that got stuck on the dead route before your fix. Toggle the workflow off and back on after applying the fix, which forces the trigger to re-establish its polling connection under the new environment.
4. Everything worked, then ETIMEDOUT returned weeks later.
A host-level change re-broke the IPv6 route, commonly a firewall ruleset reload, a provider network change, or a container network reconfiguration. Re-run the curl -6 test from Step 2. If IPv6 is dead again, the NODE_OPTIONS setting is still in place and n8n is still preferring IPv4, so look for a new, second network issue instead of reapplying the fix. If the setting itself disappeared, your compose file or unit file was overwritten by an update or a redeploy, so re-add it and put a comment in the file explaining why it is there.
FAQ
Why does the n8n Gmail Trigger work in manual runs but fail on the schedule? Manual test executions open a fresh connection each time, so they can succeed through IPv4 while the background polling connection keeps hitting the dead IPv6 route. The signature of this bug is intermittency: most poll cycles fail with ETIMEDOUT while some get through, and curl from the same server works fine.
Is ETIMEDOUT a credentials or OAuth problem? No. Credential problems produce 401 Unauthorized or refresh-token errors, not TCP timeouts. ETIMEDOUT means the socket could not reach Google’s servers at all, which is a network-layer failure. Reconnecting your Google credentials will not fix it.
Where exactly do I add NODE_OPTIONS for a systemd n8n install?
Add Environment=NODE_OPTIONS=--dns-result-order=ipv4first inside the [Service] section of /etc/systemd/system/n8n.service, then run sudo systemctl daemon-reload and sudo systemctl restart n8n. Editing the file without the daemon-reload changes nothing.
Will forcing IPv4 break anything else in n8n? On a typical VPS, nothing observable changes, because everything n8n talks to is dual-stack and reachable over IPv4. The only risk is a host that genuinely depends on IPv6-only connectivity, which is rare for self-hosted n8n in 2026. Treat the setting as reversible mitigation.
Does this fix apply to other nodes too? Yes. NODE_OPTIONS is process-wide, so it fixes ETIMEDOUT and ENETUNREACH on every outbound connection n8n makes, including HTTP Request nodes and other Google service nodes. If several unrelated integrations fail with these errors on the same server, this one fix usually cures all of them.
Conclusion
The n8n Gmail Trigger ETIMEDOUT bug is a network problem wearing an integration costume: Node.js tries Google’s IPv6 route first, the route is dead on your VPS, and the socket times out before falling back. One environment variable, NODE_OPTIONS=--dns-result-order=ipv4first, in the right place with a real restart, ends it. If you hit the sibling symptom of triggers misbehaving after a proxy or network change, our guide on fixing the n8n webhook “not registered” error behind a reverse proxy covers the ingress side of the same story, and the n8n Telegram trigger troubleshooting guide walks through trigger-specific diagnosis. For a full self-hosted setup from scratch, start with installing n8n on an Ubuntu VPS.
Frequently asked questions
Why does the n8n Gmail Trigger work in manual runs but fail on the schedule?
Manual test executions open a fresh connection each time, so they can succeed through IPv4 while the background polling connection keeps hitting the dead IPv6 route. The symptom that distinguishes this bug from credential problems is the intermittent pattern: most poll cycles fail with ETIMEDOUT while the occasional one gets through, and curl from the same server works fine.
Is ETIMEDOUT a credentials or OAuth problem?
No. Credential and OAuth problems produce 401 Unauthorized or 'refresh token expired' errors, not TCP timeouts. ETIMEDOUT means the socket could not reach Google's servers at all, which is a network-layer failure. If your error message says 'connect ETIMEDOUT' followed by an IP address and port 443, your credentials are almost certainly fine.
Where exactly do I add NODE_OPTIONS for a systemd n8n install?
Add the line Environment=NODE_OPTIONS=--dns-result-order=ipv4first inside the [Service] section of /etc/systemd/system/n8n.service, then run sudo systemctl daemon-reload and sudo systemctl restart n8n. The variable must be read when the n8n process starts, so the daemon-reload plus restart is mandatory, editing the file alone changes nothing.
Will forcing IPv4 break anything else in n8n?
On a typical VPS it changes nothing observable, because all the services n8n talks to are dual-stack and reachable over IPv4. The only scenario where it hurts is a host that genuinely depends on IPv6-only connectivity, which is rare for self-hosted n8n in 2026. Treat it as a reversible mitigation, and remove it once the underlying route is fixed.
Does this fix apply to the Gmail node too, or just the Gmail Trigger?
Both, and to every other node. NODE_OPTIONS is a process-wide Node.js setting, so it affects every outbound connection n8n makes, including HTTP Request nodes, other Google service nodes, and community nodes. If several unrelated integrations fail with ETIMEDOUT or ENETUNREACH on the same server, this single fix usually cures all of them at once.
I applied the fix and the trigger still fails. What next?
Run curl -4 -v https://www.googleapis.com/gmail/v1/users/me/profile from the server. If even that times out, your outbound firewall is blocking port 443 to Google's IP ranges entirely, and no Node.js setting can help. You need the network admin to whitelist *.googleapis.com. If curl -4 works but n8n still fails, verify the variable is actually in the running process with systemctl show n8n | grep NODE_OPTIONS.