OpenClaw merged a channel trust-boundary fix this morning with PR #114998, "fix(channels): Slack stops receiving messages while reporting healthy when its plugin is not a trusted install". The bug affected operators loading Slack as an untrusted source-path plugin instead of an official trusted install.
The visible failure mode was nasty: Slack could report as enabled, configured, running, connected, and healthy while no inbound Slack events were processed. At the same time, Gateway logs filled with one low-severity ingress failure per second.
The Failure Mode
The root issue was not that OpenClaw denied the state capability. openChannelIngressQueue is intentionally restricted to bundled plugins and trusted official installs. Slack ships as @openclaw/slack, so a source checkout loaded through plugins.load.paths is supposed to be untrusted.
The bug was how that denial surfaced. The channel ingress monitor opened its durable queue lazily. Startup succeeded, the poll timer armed, and every tick retried the same failing queue factory. The result was a channel that looked healthy from the outside while it could not admit inbound events.
The PR notes production evidence from Slack over Socket Mode: roughly 3,550 occurrences per hour, sustained across the retained log window, with the error logged at INFO. Since the channel status still looked healthy, operators had little reason to suspect ingress was completely blocked.
What Changed
The monitor now opens the queue before arming the poll timer. If the channel cannot access its durable ingress queue, startup fails immediately through the existing channel-start failure path.
That changes the operational story from silent loss to visible action:
- The channel no longer reports healthy when ingress cannot work.
- The log no longer repeats the same unrecoverable line every second.
- The failure names the denied capability.
- The message identifies the plugin and where it was loaded from.
- The remediation points operators back to the official npm package or ClawHub listing.
The PR deliberately keeps the trust classification unchanged. That is the right call. Expanding trusted state access to any sideloaded plugin would make the symptom disappear by weakening the boundary.
Operator Impact
For anyone already in this state, the fix makes the problem loud but does not magically convert a source-linked plugin into a trusted install. The PR's documented remedy is to install Slack from the official package, for example openclaw plugins install @openclaw/slack, remove the matching plugins.load.paths entry from openclaw.json, and restart Gateway.
Trusted and bundled channel plugins are unaffected. The PR includes a trusted-path control showing that a bundled Slack plugin opens the queue, starts the monitor, and admits an inbound event through the same shared monitor path.
Verification
The maintainers reproduced the before state with a real Node process and production code paths: a config-origin Slack plugin, the same queue factory Slack calls, and the 1000 ms poll interval. Before the fix, monitor.start() returned normally, the monitor reported running, and repeated drain errors appeared.
After the fix, monitor.start() threw immediately, the monitor did not run, and no interval spam was emitted. New regression coverage asserts that startup throws, the factory is invoked exactly once, onError is not called repeatedly, and admit() still fails closed.
The changed suites passed through node scripts/run-vitest.mjs, and node scripts/check-changed.mjs covered core typecheck, test typecheck, lint, format, plugin boundaries, and SDK contract validation.
Bottom Line
PR #114998 keeps OpenClaw's plugin trust boundary intact while making Slack ingress failures visible. A channel that cannot receive messages should fail startup with a repair path, not look healthy while dropping every inbound event.