#Gmail Sub/Pub Push Problems

1 messages · Page 1 of 1 (latest)

barren hearth
#

Having an issue with Gmail Pub/Sub integration where pushes are being received but ignored.

Setup:

  • Linux Mint 22 (bare metal, not macOS)
  • OpenClaw 2026.3.8
  • gog v0.12.0
  • Tailscale Funnel on /gmail-pubsub → port 8788
  • hooks.enabled: true, gmail preset configured
  • Running openclaw webhooks gmail run manually on host (gateway runs in Docker and can't access gog)
sick sorrelBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> ✅ Mark Solution

south meteorBOT
#

Most likely root cause here is path rewriting with Tailscale Funnel.

With Funnel on /gmail-pubsub, Tailscale usually strips that prefix before proxying.
So if gog gmail watch serve is listening on --path /gmail-pubsub, pushes can hit / locally and get dropped/ignored.

Try this first

Run the Gmail watcher with backend path /:

openclaw webhooks gmail run \
--path / \
--hook-url http://127.0.0.1:18789/hooks/gmail \
--hook-token <hooks.token> \
--push-token <push-token>

(Keep public path at /gmail-pubsub on Funnel side.)

#

Fast isolate checks (in order)

  1. Verify direct OpenClaw hook works
curl -i -X POST http://127.0.0.1:18789/hooks/gmail \
-H "Authorization: Bearer <hooks.token>" \
-H "Content-Type: application/json" \
-d '{"source":"gmail","messages":[{"id":"t1","from":"test","subject":"hello","snippet":"ping","body":"pong"}]}'

Should return 200. If not, it’s hook config/token/mapping.

  1. Check response code from gog → OpenClaw
  • 401 = hooks.token mismatch
  • 404 = wrong hook path (hooks.path not /hooks)
  • 400 hook mapping requires message = payload not matching template / empty messages[0]
#
  1. Confirm config parity (host vs Docker)
    Since gateway is in Docker but watcher is on host, make sure the host openclaw webhooks gmail run is using the same config values (especially hooks.token, hooks.path, hook URL).

  2. Version sanity (both sides)
    Please paste:

openclaw --version
gog --version

(and container OpenClaw version too, if different image/runtime)

Docs:

If you paste one failing gog log line + the matching hook HTTP status, I can pinpoint it quickly.

barren hearth
south meteorBOT
#

Perfect, that log line is super useful — and it confirms this is upstream of OpenClaw.

ignoring stale push historyId=4461 (stored=4461) means gog is receiving a notification that does not advance Gmail history, so it intentionally drops it. OpenClaw never gets called in that case.

What to do next

  1. Check whether history is actually advancing
gog gmail watch status --account <your@gmail.com>
gog gmail history --account <your@gmail.com> --since 4461

Then send a truly new test email from a different sender to INBOX.

  1. If pushes keep replaying same historyId, clear Pub/Sub backlog
gcloud pubsub subscriptions seek <subscription> \
#
--time="$(date -u +%Y-%m-%dT%H:%M:%SZ)"

(If seek isn’t available in your setup, recreate the push subscription.)

  1. Reset watch baseline
gog gmail watch stop --account <your@gmail.com>
gog gmail watch start \
--account <your@gmail.com> \
--label INBOX \
--topic projects/<project-id>/topics/<topic>

Then restart:

openclaw webhooks gmail run ...
barren hearth
#

nothing appears in output line when test email arrives. It isn't until I stop and restart the watcher that I will sometimes get a stale push from that email before.

#

~$ openclaw --versionon
gog --version
OpenClaw 2026.3.8 (3caab92)
v0.12.0 (c18c58c 2026-03-09T05:53:14Z)

south meteorBOT
#

Nice — versions are good (OpenClaw 2026.3.8, gog 0.12.0), so this isn’t an old-build mismatch.

Also: historyId=stored right after startup is often normal (initial/no-op push).
The key question is whether history advances after a real new INBOX message.

Can you run this exact check?

# 1) capture baseline
gog gmail watch status --account <your@gmail.com>

# 2) send a NEW external email to that inbox (from another account)

# 3) inspect history since baseline id
gog gmail history --account <your@gmail.com> --since <baselineHistoryId>
#

If step 3 shows entries but watcher still logs only:
ignoring stale push historyId=... (stored=...)
then we’re in Pub/Sub replay/backlog territory and we should do:

  • watch stop/start
  • subscription seek-to-now (or recreate subscription)

If step 3 is empty, it’s label/filter side (INBOX change not happening), not OpenClaw.

If you paste the watch status + history --since output, I can tell you the exact next command set.

barren hearth
#

~gog gmail watch status --account assistant@plebelectric.comom
gog gmail history --account assistant@plebelectric.com --since 4461
account assistant@plebelectric.com
topic projects/rock-sublime-491020-b5/topics/gog-gmail-watch
labels INBOX
history_id 4734
expiration 2026-03-30T08:57:49-07:00
provider_expiration 2026-03-30T08:57:49-07:00
updated_at 2026-03-23T09:06:38-07:00
last_delivery_status ok
last_delivery_at 2026-03-23T09:06:38-07:00
last_push_message_id 18695253501857180
MESSAGE_ID
19d1b3721abf4480
19d1b3b14d40afd9
19d1b62b8ad91d2c
19d1b6c1d231243d
19d1b72a5ba8500b

south meteorBOT
#

This is great data — and it changes the diagnosis:

  • history_id moved from 4461 → 4734
  • gog gmail history --since 4461 returned message IDs
  • last_delivery_status ok

So the stale message was likely just a duplicate/no-op push.
Your watcher is actually processing new history now.

What’s likely broken now

Not Pub/Sub ingestion — likely OpenClaw hook delivery target.

With just the Gmail preset, delivery defaults to channel: "last" (and can fall back in ways that aren’t this Discord thread). So it may be running, just not posting where you expect.

Fix: pin delivery explicitly

Add an explicit Gmail mapping with deliver + channel + to (Discord thread/channel id):

#
{
hooks: {
presets: ["gmail"],
mappings: [
{
match: { path: "gmail" },
action: "agent",
wakeMode: "now",
name: "Gmail",
sessionKey: "hook:gmail:{{messages[0].id}}",
messageTemplate: "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}",
deliver: true,
channel: "discord",
to: "1485661609522102384"
}
#
]
}
}

Then restart gateway + openclaw webhooks gmail run.

If you want, paste your current hooks block and I’ll sanity-check it line-by-line.

barren hearth
#

maxip2@maxip2-OptiPlex-5050:~$ cat ~/.openclaw/openclaw.json | python3 -c "
import sys, json
d = json.load(sys.stdin)
h = d.get('hooks', {})
if 'token' in h: h['token'] = 'REDACTED'
if 'gmail' in h:
if 'pushToken' in h['gmail']: h['gmail']['pushToken'] = 'REDACTED'
if 'hookToken' in h['gmail']: h['gmail']['hookToken'] = 'REDACTED'
print(json.dumps(h, indent=2))
"
{
"enabled": true,
"path": "/hooks",
"token": "REDACTED",
"presets": [
"gmail"
],
"gmail": {
"account": "assistant@plebelectric.com",
"label": "INBOX",
"topic": "projects/rock-sublime-491020-b5/topics/gog-gmail-watch",
"subscription": "gog-gmail-watch-push",
"pushToken": "REDACTED",
"hookUrl": "http://127.0.0.1:18789/hooks/gmail",
"includeBody": true,
"maxBytes": 20000,
"renewEveryMinutes": 720,
"serve": {
"bind": "127.0.0.1",
"port": 8788,
"path": "/"
},
"tailscale": {
"mode": "funnel",
"path": "/gmail-pubsub"
}
}
}

south meteorBOT
#

This host-side hooks config looks correct for the watcher path. ✅

The two likely remaining issues are:

  1. No explicit delivery mapping (preset defaults to channel: "last", which may not be this Discord thread), and/or
  2. Config mismatch host vs Docker gateway (host ~/.openclaw/openclaw.json can differ from what container is actually using).

1) Add explicit Gmail delivery mapping

Right now you only have presets: ["gmail"]. Add a mapping with explicit Discord target:

hooks: {
enabled: true,
path: "/hooks",
#
token: "...",
presets: ["gmail"],
mappings: [
{
match: { path: "gmail" },
action: "agent",
wakeMode: "now",
name: "Gmail",
sessionKey: "hook:gmail:{{messages[0].id}}",
messageTemplate: "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}",
deliver: true,
channel: "discord",
to: "1485661609522102384"
}
]
#
}

2) Verify gateway accepts the same token the watcher uses

From host, test directly:

curl -i -X POST http://127.0.0.1:18789/hooks/gmail \
-H "Authorization: Bearer <hooks.token>" \
-H "Content-Type: application/json" \
-d '{"source":"gmail","messages":[{"id":"test-1","from":"a","subject":"b","snippet":"c","body":"d"}]}'

Expect 200 + runId.