Skip to content

[Bug]: Telegram /approve allow-always writes 'source' field that openclaw approvals set --gateway rejects — allowlist updates silently fail to persist to gateway #69482

@reidperyam

Description

@reidperyam

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

  1. 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).

  2. In Telegram, tap "Allow always" on the inline button.

  3. 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"
    }

  4. Attempt to push the file to the gateway:

    openclaw approvals set --gateway --file ~/.openclaw/exec-approvals.json

  5. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingbug:behaviorIncorrect behavior without a crash

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions