#11280: fix(gateway): add meta prefix to reload rules to prevent double SIGUSR1
gateway
stale
Cluster:
Gateway Hot-Reload Improvements
## Summary
Adds `{ prefix: "meta", kind: "none" }` to the `BASE_RELOAD_RULES` array to prevent `meta.lastTouchedAt` config changes from triggering unnecessary gateway restarts.
## Problem
When `config.patch` writes the configuration file:
1. It updates `meta.lastTouchedAt` (`src/config/io.ts:143`)
2. It schedules a SIGUSR1 restart
But the file watcher also detects this change, and since `meta.*` paths have no reload rule, they fall through to the default `restartGateway = true` path — triggering a **second SIGUSR1** ~1.4 seconds later.
### Evidence from logs:
```
04:58:49.469Z config change requires gateway restart (meta.lastTouchedAt)
04:58:49.471Z signal SIGUSR1 received
04:58:49.520Z cron: started
04:58:50.946Z signal SIGUSR1 received ← SECOND SIGUSR1
04:58:52.498Z cron: started
```
## Root Cause
In `src/gateway/config-reload.ts`, the `BASE_RELOAD_RULES` array lacks a rule for the `meta` prefix. When `buildGatewayReloadPlan()` processes `meta.lastTouchedAt`, it finds no matching rule and defaults to `restartGateway = true` (line 226).
## Fix
Add the `meta` prefix to the no-op rules:
```diff
const BASE_RELOAD_RULES: ReloadRule[] = [
{ prefix: "gateway.remote", kind: "none" },
{ prefix: "gateway.reload", kind: "none" },
+ { prefix: "meta", kind: "none" },
{ prefix: "hooks.gmail", kind: "hot", actions: ["restart-gmail-watcher"] },
```
The `meta` section contains bookkeeping metadata (`lastTouchedAt`, `version`) that should never trigger a gateway restart.
## Impact
This double-restart:
- Causes unnecessary service disruption
- Creates race conditions during rapid restart cycles
- Exacerbates timer GC issues during idle periods (the restart flurry can cause cron timers to be garbage collected before the server is fully listening)
## Testing
All existing tests pass:
```
✓ src/gateway/config-reload.test.ts (8 tests)
✓ src/cron/ (86 tests)
```
## Related Issues
Fixes: #11279
Fixes: #5533
Related:
- #11013 — Cron scheduler stalls after SIGUSR1 restart
- #10849 — Cron scheduler timer never fires
- #9084 — Heartbeat timer stops after macOS sleep/wake
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR updates the gateway config reload rules so that config changes under the `meta.*` prefix are treated as no-ops.
Concretely, it adds `{ prefix: "meta", kind: "none" }` to `BASE_RELOAD_RULES` in `src/gateway/config-reload.ts`, which aligns with the current config schema where `meta.lastTouchedVersion` / `meta.lastTouchedAt` are auto-stamped bookkeeping fields when OpenClaw writes the config. Without this rule, `buildGatewayReloadPlan()` treats unknown config paths as requiring a full gateway restart, which can lead to a second SIGUSR1 restart when the file watcher observes the `meta.lastTouchedAt` write.
Change scope is limited to reload planning logic; no other behavior is modified.
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk.
- The change is a single additional reload rule and matches existing config schema semantics: `meta` is strictly defined as optional bookkeeping fields that are auto-written by OpenClaw. Adding it to the no-op prefix list prevents unnecessary restarts without impacting operational config reload decisions.
- No files require special attention
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#8473: fix(gateway): prevent spurious restarts on meta.lastTouchedAt changes
by adam-smeth · 2026-02-04
93.2%
#11746: fix: treat meta config paths as no-op to prevent unnecessary gatewa...
by QDenka · 2026-02-08
90.7%
#13408: fix(gateway): skip SIGUSR1 restart in config.patch for noop reload ...
by rwmjhb · 2026-02-10
82.3%
#7747: Gateway: add zero-latency hot-reload for agent bindings
by NikolasP98 · 2026-02-03
78.0%
#4108: gateway: hot-reload heartbeat when agents.list changes
by jifanchn · 2026-01-29
77.8%
#9112: Fix: Prevent double SIGUSR1 restart on model switch
by vishaltandale00 · 2026-02-04
77.1%
#12953: fix: defer gateway restart until all replies are sent
by zoskebutler · 2026-02-10
76.1%
#20355: fix(gateway): enforce commands.restart guard for config.apply and c...
by Clawborn · 2026-02-18
75.7%
#16170: fix: restart service manager after update.run
by Swader · 2026-02-14
75.5%
#22720: fix: notify sessions on invalid config during hot-reload
by jayleekr · 2026-02-21
74.8%