Bug type
Behavior bug (incorrect output/state without crash)
Beta release blocker
No
Summary
Telegram "Allow always" approvals write an allowlist entry with a source: "allow-always" string field. The file write to ~/.openclaw/exec-approvals.json succeeds, but openclaw approvals set --gateway --file <path> then rejects every entry containing source with invalid exec.approvals.set params: unexpected property 'source'. The gateway never receives the new policy. User-visible symptom: "Allow always" silently fails to persist.
Steps to reproduce
-
On an install with a Telegram binding configured with directPolicy: "allow", trigger an exec approval prompt from any agent (any exec call that hits on-miss under the current allowlist).
-
In Telegram, tap "Allow always" on the inline button.
-
Inspect the resulting allowlist entry in ~/.openclaw/exec-approvals.json. Example captured from a production install:
{
"pattern": "/usr/bin/curl",
"lastUsedAt": 1776563902217,
"id": "ed8f2b4b-20be-4965-bf23-9701d3cd6e1d",
"lastUsedCommand": "curl -s http://localhost:8000/health",
"lastResolvedPath": "/usr/bin/curl",
"source": "allow-always"
}
-
Attempt to push the file to the gateway:
openclaw approvals set --gateway --file ~/.openclaw/exec-approvals.json
-
Observe the rejection error listing every entry containing source.
Minimal synthetic reproducer (does not require Telegram): construct any allowlist entry with a literal source: "allow-always" field and push via --gateway. Same rejection occurs.
Expected behavior
Either the gateway schema accepts source as an optional string property on allowlist entries (preferred — since Telegram's own approval handler writes it, the schema should describe what's actually on disk), OR the Telegram approval handler stops writing a field the gateway will reject. Whatever the fix, openclaw approvals set (local write) and openclaw approvals set --gateway (gateway push) should agree on the schema — currently the local-write path accepts source without complaint while the gateway path rejects it.
Actual behavior
openclaw approvals set --gateway --file ~/.openclaw/exec-approvals.json exits nonzero with:
invalid exec.approvals.set params: at /file/agents/maelcum/allowlist/5: unexpected property 'source'; at /file/agents/maelcum/allowlist/6: unexpected property 'source'; at /file/agents/maelcum/allowlist/7: unexpected property 'source'; at /file/agents/maelcum/allowlist/8: unexpected property 'source...
Error is truncated at terminal output width. One rejection is emitted per allowlist entry containing source. No policy update reaches the gateway; on-disk file and gateway in-memory state drift apart. Full error text attached as bug-source-field-error.txt.
bug-source-field-error.txt
OpenClaw version
2026.4.14 (323493f)
Operating system
macOS 26.4.1
Install method
npm global, latest stable as of filing
Model
N/A — bug is in approvals subsystem, not model-dependent
Provider / routing chain
N/A — bug is in approvals subsystem, not provider-dependent
Additional provider/model setup details
Host: Mac Mini M4 Pro, 48 GB unified memory. Gateway supervised by launchd, loopback bind on port 18789. Telegram binding has dmPolicy: "allowlist" with directPolicy: "allow" — so exec approvals are being requested and "Allow always" is a real user-facing flow on this install. Over ~3 weeks of normal use, 13 allowlist entries across 8 agent scopes accumulated the source: "allow-always" field, rendering the whole allowlist un-pushable without a strip pass.
Logs, screenshots, and evidence
Attached: bug-source-field-error.txt — full rejection error from `openclaw approvals set --gateway --file`.
Secondary finding worth noting: `openclaw approvals set` WITHOUT --gateway accepts files containing `source` without complaint and writes them through to disk. Only the --gateway path rejects. The two modes disagree about what constitutes a valid allowlist shape.
Related: #69478 (enqueueSystemEvent duplicate-approval cascade). Distinct bug but same subsystem and same user-visible symptom ("my approvals don't stick"). A user hitting both simultaneously cannot distinguish them without reading gateway logs.
Impact and severity
Affected: any install where users tap "Allow always" on Telegram exec approval prompts.
Severity: High — silently breaks the persistence contract of "Allow always" and causes unbounded drift between on-disk allowlist and gateway in-memory state.
Frequency: Every "Allow always" tap produces an unpushable entry. Deterministic, 100% reproduction on my install.
Consequence: Users experience "OpenClaw isn't remembering my approvals." Any automation that reads ~/.openclaw/exec-approvals.json and pushes it to the gateway breaks on the first Telegram-originated entry. Workaround is a strip pass over every entry before every gateway push.
Additional information
Last known good version: unknown — "Allow always" may never have worked cleanly against the gateway on this install. I adopted the strip-before-push workaround early and never had a period of normal operation to compare against. If the gateway schema was ever widened to accept source, that change is not visible to me from the CLI behavior alone.
Workaround in use: sync script strips source from every allowlist entry before every openclaw approvals set --gateway --file call. This has kept the system functional but means ~/.openclaw/exec-approvals.json on disk drifts from what actually reaches the gateway.
Bug type
Behavior bug (incorrect output/state without crash)
Beta release blocker
No
Summary
Telegram "Allow always" approvals write an allowlist entry with a
source: "allow-always"string field. The file write to ~/.openclaw/exec-approvals.json succeeds, butopenclaw approvals set --gateway --file <path>then rejects every entry containingsourcewithinvalid exec.approvals.set params: unexpected property 'source'. The gateway never receives the new policy. User-visible symptom: "Allow always" silently fails to persist.Steps to reproduce
On an install with a Telegram binding configured with directPolicy: "allow", trigger an exec approval prompt from any agent (any exec call that hits on-miss under the current allowlist).
In Telegram, tap "Allow always" on the inline button.
Inspect the resulting allowlist entry in ~/.openclaw/exec-approvals.json. Example captured from a production install:
{
"pattern": "/usr/bin/curl",
"lastUsedAt": 1776563902217,
"id": "ed8f2b4b-20be-4965-bf23-9701d3cd6e1d",
"lastUsedCommand": "curl -s http://localhost:8000/health",
"lastResolvedPath": "/usr/bin/curl",
"source": "allow-always"
}
Attempt to push the file to the gateway:
openclaw approvals set --gateway --file ~/.openclaw/exec-approvals.json
Observe the rejection error listing every entry containing
source.Minimal synthetic reproducer (does not require Telegram): construct any allowlist entry with a literal
source: "allow-always"field and push via --gateway. Same rejection occurs.Expected behavior
Either the gateway schema accepts
sourceas an optional string property on allowlist entries (preferred — since Telegram's own approval handler writes it, the schema should describe what's actually on disk), OR the Telegram approval handler stops writing a field the gateway will reject. Whatever the fix,openclaw approvals set(local write) andopenclaw approvals set --gateway(gateway push) should agree on the schema — currently the local-write path acceptssourcewithout complaint while the gateway path rejects it.Actual behavior
openclaw approvals set --gateway --file ~/.openclaw/exec-approvals.json exits nonzero with:
invalid exec.approvals.set params: at /file/agents/maelcum/allowlist/5: unexpected property 'source'; at /file/agents/maelcum/allowlist/6: unexpected property 'source'; at /file/agents/maelcum/allowlist/7: unexpected property 'source'; at /file/agents/maelcum/allowlist/8: unexpected property 'source...
Error is truncated at terminal output width. One rejection is emitted per allowlist entry containing
source. No policy update reaches the gateway; on-disk file and gateway in-memory state drift apart. Full error text attached as bug-source-field-error.txt.bug-source-field-error.txt
OpenClaw version
2026.4.14 (323493f)
Operating system
macOS 26.4.1
Install method
npm global, latest stable as of filing
Model
N/A — bug is in approvals subsystem, not model-dependent
Provider / routing chain
N/A — bug is in approvals subsystem, not provider-dependent
Additional provider/model setup details
Host: Mac Mini M4 Pro, 48 GB unified memory. Gateway supervised by launchd, loopback bind on port 18789. Telegram binding has dmPolicy: "allowlist" with directPolicy: "allow" — so exec approvals are being requested and "Allow always" is a real user-facing flow on this install. Over ~3 weeks of normal use, 13 allowlist entries across 8 agent scopes accumulated the
source: "allow-always"field, rendering the whole allowlist un-pushable without a strip pass.Logs, screenshots, and evidence
Impact and severity
Affected: any install where users tap "Allow always" on Telegram exec approval prompts.
Severity: High — silently breaks the persistence contract of "Allow always" and causes unbounded drift between on-disk allowlist and gateway in-memory state.
Frequency: Every "Allow always" tap produces an unpushable entry. Deterministic, 100% reproduction on my install.
Consequence: Users experience "OpenClaw isn't remembering my approvals." Any automation that reads ~/.openclaw/exec-approvals.json and pushes it to the gateway breaks on the first Telegram-originated entry. Workaround is a strip pass over every entry before every gateway push.
Additional information
Last known good version: unknown — "Allow always" may never have worked cleanly against the gateway on this install. I adopted the strip-before-push workaround early and never had a period of normal operation to compare against. If the gateway schema was ever widened to accept
source, that change is not visible to me from the CLI behavior alone.Workaround in use: sync script strips
sourcefrom every allowlist entry before everyopenclaw approvals set --gateway --filecall. This has kept the system functional but means~/.openclaw/exec-approvals.jsonon disk drifts from what actually reaches the gateway.