Feishu Channel WebSocket Mode: client.on is not a function
The Feishu channel crashes on startup with 'client.on is not a function' due to WebSocket client initialization failure in OpenClaw 2026.2.26.
๐ Symptoms
Primary Error Manifestation
The Feishu channel terminates immediately upon initialization with a TypeError:
[default] channel exited: client.on is not a functionExecution Context
The error occurs during the WebSocket handshake phase, as evidenced by the log sequence:
{"subsystem":"gateway/channels/feishu","1":"starting feishu[default] (mode: websocket)"}
{"subsystem":"gateway/channels/feishu","1":"feishu[${accountId}]: bot open_id resolved: ${botOpenId ?? \"unknown\"}"}
{"subsystem":"gateway/channels/feishu","1":"[default] channel exited: client.on is not a function"}
{"subsystem":"gateway/channels/feishu","1":"[default] auto-restart attempt 3/10 in 20s"}Diagnostic Observations
- Bot identity resolution succeeds: The `open_id` log entry confirms API authentication (appId/appSecret) is functional.
- Outbound communication unaffected: Sending messages via the Feishu channel works correctly.
- Inbound processing broken: No incoming messages from Feishu users are processed.
- Retry loop initiated: The channel enters a continuous restart cycle with exponential backoff.
CLI Inspection Commands
To manually diagnose this condition:
# Check OpenClaw version
openclaw --version
# Expected: OpenClaw v2026.2.26
# Verify Feishu channel configuration
openclaw config get channels.feishu
# View real-time logs (if logging level permits)
openclaw logs --follow --filter feishu๐ง Root Cause
Architectural Failure Point
The error client.on is not a function originates from an incorrect WebSocket client initialization in the Feishu channel adapter. The code attempts to attach event listeners to a client object that lacks the expected EventEmitter-compatible API.
Failure Sequence Analysis
- Channel Initialization: OpenClaw instantiates the Feishu channel adapter in WebSocket mode.
- Client Creation: The adapter calls the WebSocket library constructor.
- API Mismatch: The code expects a standard WebSocket object with `.on(event, handler)` methods, but receives either:
- A raw HTTP client response object
- An improperly wrapped WebSocket connection
- A WebSocketShim instance with incompatible API surface
- Event Binding Failure: The call to `client.on('message', handler)` throws
TypeError: client.on is not a function. - Graceful Termination: The channel catches the error and exits with the reported message.
Probable Code Path
The problematic initialization likely follows this pattern:
// Hypothetical incorrect implementation (simplified)
const WebSocket = require('ws');
class FeishuChannel {
async connect(config) {
const wsUrl = await this.obtainWebSocketEndpoint(config);
// BUG: Using WebSocket constructor directly instead of proper connection
const client = new WebSocket(wsUrl); // Returns WRONG object type
// This fails because 'client' is not an EventEmitter
client.on('message', (data) => this.handleMessage(data));
client.on('error', (err) => this.handleError(err));
return client;
}
}Dependency Context
The ws library (or equivalent) should return an object with these methods:
on(event: string, listener: Function): thisonce(event: string, listener: Function): thisoff(event: string, listener: Function): thissend(data: string | ArrayBuffer): void
If the returned object lacks .on(), the channel adapter was likely modified between versions, or a dependency version mismatch altered the return type.
Version Correlation
The regression appeared in OpenClaw 2026.2.26, indicating a recent change to either:
- The Feishu channel adapter code
- A WebSocket library dependency version
- The build/bundling process affecting module resolution
๐ ๏ธ Step-by-Step Fix
Method 1: Downgrade OpenClaw (Immediate Relief)
If immediate production stability is required, downgrade to a known-working version:
# Stop OpenClaw service
sudo systemctl stop openclaw # Linux
# or
launchctl unload ~/Library/LaunchAgents/com.openclaw.plist # macOS
# Install previous stable version
npm install -g [email protected]
# Restart service
sudo systemctl start openclaw
# or
launchctl load ~/Library/LaunchAgents/com.openclaw.plistMethod 2: Switch to HTTP Long-Polling Mode (Recommended)
The WebSocket mode is unstable; switch to HTTP long-polling as an interim workaround:
{
"channels": {
"feishu": {
"enabled": true,
"dmPolicy": "pairing",
"mode": "polling",
"accounts": {
"default": {
"appId": "cli_a90c15147a38dcb3",
"appSecret": "***",
"botName": "Claw",
"pollingIntervalMs": 30000
}
}
}
}
}Note: If the configuration field mode is not recognized, proceed to Method 3.
Method 3: Apply Manual Patch (Temporary Fix)
Identify and patch the Feishu channel adapter source file:
# Locate the Feishu channel adapter
find /usr/local/lib/node_modules/openclaw -name "feishu*.js" 2>/dev/null
# or
find ~/.openclaw -name "feishu*.js" 2>/dev/null
# Common paths:
# /usr/local/lib/node_modules/openclaw/dist/gateway/channels/feishu/index.js
# ~/.openclaw/plugins/feishu/dist/index.jsApply the following patch to the WebSocket initialization section:
// BEFORE (buggy):
const ws = new WebSocket(url);
ws.on('message', handler);
// AFTER (patched):
const WebSocket = require('ws');
const ws = new WebSocket(url);
// Verify the client has the expected API, wrap if necessary
if (typeof ws.on !== 'function') {
// Fallback: use EventEmitter-style wrapper
const { EventEmitter } = require('events');
const client = new EventEmitter();
ws.onmessage = (event) => client.emit('message', event.data);
ws.onerror = (event) => client.emit('error', event);
ws.onopen = (event) => client.emit('open', event);
ws.onclose = (event) => client.emit('close', event);
// Replace ws with wrapped client
Object.assign(ws, client);
}Method 4: Force WebSocket Library Override (Advanced)
If a dependency version conflict is suspected, force-load the correct WebSocket implementation:
# Check current ws dependency version
cd /usr/local/lib/node_modules/openclaw
npm ls ws
# Install specific compatible version
npm install [email protected] --saveAdd to OpenClaw configuration (~/.openclaw/config.json):
{
"feishu": {
"websocketOptions": {
"resolveSocket": true,
"library": "ws"
}
}
}๐งช Verification
Confirm Fix Success
After applying any fix method, verify the Feishu channel connects successfully:
Step 1: Restart OpenClaw Service
# Linux
sudo systemctl restart openclaw
# macOS
launchctl unload ~/Library/LaunchAgents/com.openclaw.plist
launchctl load ~/Library/LaunchAgents/com.openclaw.plist
# Or via PM2 (if using process manager)
pm2 restart openclawStep 2: Check Channel Status
openclaw status --channel feishu
# Expected output:
# feishu[default]: connected
# feishu[default]: mode: websocket # or "polling" if using Method 2
# feishu[default]: uptime: 0d 0h 1mStep 3: Verify WebSocket Connection (WebSocket Mode Only)
# Check for active WebSocket connection on port 9000 (default)
lsof -i :9000 | grep openclaw
# or
netstat -tlnp | grep 9000
# Expected: LISTEN or ESTABLISHED stateStep 4: Test Inbound Message Reception
Send a test message from a Feishu user to the bot:
# Monitor logs for incoming message
openclaw logs --follow --filter "feishu.*incoming"
# Send a message from Feishu app to the bot
# Expected log entry:
# {"subsystem":"gateway/channels/feishu","1":"feishu[default]: incoming message from user ${userId}"}
# {"subsystem":"gateway/channels/feishu","1":"feishu[default]: message processed successfully"}Step 5: Verify No Restart Loop
# Check process uptime
pm2 list
# or
ps aux | grep openclaw
# Expected: stable uptime without auto-restart entries in logsExpected Successful Log Sequence
{"subsystem":"gateway/channels/feishu","1":"starting feishu[default] (mode: websocket)"}
{"subsystem":"gateway/channels/feishu","1":"feishu[${accountId}]: bot open_id resolved: ${botOpenId}"}
{"subsystem":"gateway/channels/feishu","1":"feishu[default]: WebSocket connected"}
{"subsystem":"gateway/channels/feishu","1":"feishu[default]: channel ready"}Exit Code Verification
# Check that the process is stable (no rapid exit)
echo $?
# Expected: 0 (process running)
# If channel is working, no 'exited' messages should appearโ ๏ธ Common Pitfalls
- Configuration Caching: OpenClaw may cache channel configurations. Always restart the service after config changes, and delete `~/.openclaw/cache/` if issues persist.
- Polling Mode Not Recognized: The `mode: "polling"` configuration field may not exist in v2026.2.26. Check the channel schema with
openclaw config schema channels.feishubefore assuming it will work. - WebSocket Library Version Conflicts: If OpenClaw is installed globally alongside project-local dependencies, npm may resolve different `ws` versions. Audit with
npm ls wsin both contexts. - Node.js Version Incompatibility: Node v25.6.0 is a very recent release. Some native WebSocket addons may not be prebuilt for this version. Consider using Node v22.x LTS as a workaround.
- macOS ARM64 Build Artifacts: On Apple Silicon, cached native modules from x86_64 builds can cause silent failures. Run
npm rebuildafter any WebSocket library changes. - Docker Environment Isolation: If running OpenClaw in Docker, ensure the WebSocket library is installed inside the container, not mounted from the host. Volume mounts can override
node_moduleswith incompatible builds. - Feishu API Rate Limiting: During the restart loop, multiple reconnection attempts may trigger Feishu's API rate limits, causing secondary authentication failures. Limit restart attempts or implement backoff.
- Credential Rotation: If the appSecret was recently rotated on the Feishu Open Platform, the cached credentials in configuration may be stale. Re-enter credentials in the config file.
- Channel Priority Conflicts: If multiple Feishu accounts are defined, the channel may attempt to initialize the wrong account first. Explicitly set
"defaultAccount": "default"at the channel level.
๐ Related Errors
Contextual Error References
EADDRINUSE 9000: WebSocket port conflict. Indicates another process is using the Feishu WebSocket gateway port. Check withlsof -i :9000.WebSocket connection failed: 401 Unauthorized: The Feishu app credentials (appId/appSecret) are invalid or expired. Verify credentials on the Feishu Open Platform.Feishu API error: app_access_token invalid: Token refresh failure. The channel cannot obtain a valid access token. Check system time synchronization.channel exited: UnhandledPromiseRejection: Async initialization failure in the channel adapter. May be a precursor to theclient.onerror if promises are not properly handled.auto-restart loop detected: OpenClaw's built-in protection against rapid restart cycles. Appears after 10 failed attempts in 2026.2.26. Useopenclaw debugto bypass.Cannot find module 'ws': Missing WebSocket dependency. Occurs ifnpm installwas run with--omit=optional. Reinstall withnpm install.ECONNREFUSED: The Feishu WebSocket gateway is unreachable. Check firewall rules and corporate proxy settings.Historical: feishu channel not starting after v2025.x update: Previously documented regression with different error message. Indicates ongoing stability issues with the Feishu channel WebSocket implementation.