Lesson 3 — When nothing happens
Treat “connected but quiet” as a capability audit: intents, secrets, subscriptions, and negotiated surface.
Most confusing failures are not random WebSocket bugs. They are mismatched expectations between what your bot can emit, what your secret allows, and what your app subscribed to.
1. Handlers never run
Work through this list in order:
app.capabilities().events— is the event you subscribed to actually listed?- Bot intents on
createBotBridge— missing intents silently remove events from negotiation (Bot bridge). - Scoped secrets — if you narrowed
allow.events, the event must be permitted for that secret (Capabilities & scoped secrets). - Subscription name — typo in
app.on('messageCreate', …)?
2. Actions return ok: false
- Branch on
result.okand logresult.error.code(App bridge). - Confirm the action appears in negotiated capabilities (not just your local wish list).
3. Strict startup surprises
Register handlers before `ready({ strict: true })`
If you call app.on(...) after await app.ready({ strict: true, … }), strict startup cannot see those subscriptions and startup may fail or your contract will not match reality. Register handlers first, then call ready.
See Strict startup and Incremental adoption when you add manifests.
4. Still stuck
Use Troubleshooting and Diagnostics — treat it as a capability audit first, then transport.
You now have a working local bridge. When you ship beyond loopback, continue with Deployment and Remote bridge (wss).