Troubleshooting
A running list of the most common things that trip people up. Start at the top — the first two account for probably 80% of the issues we see.
Realtime fails to connect in Node.js
Symptom: whisp.realtime.connect() throws, or you see “WebSocket is not defined” in your logs.
Cause: You forgot to pass webSocketImpl to the WhispClient constructor. Node.js has no built-in WebSocket, so the SDK needs you to hand it one.
Fix:
npm install ws
import WebSocket from "ws";
const whisp = new WhispClient({
baseUrl: "…",
apiKey: process.env.WHISP_API_KEY,
webSocketImpl: WebSocket, // <-- this line
});
See Installation → Node.js for the full rundown.
Realtime fails to connect in the browser
Checklist:
- Confirm the client is authenticated — you called
signIn()(Node) orsetAuth()(browser).whisp.isAuthenticatedshould betrue. - Call
await whisp.realtime.connect()after auth is set. - If you’re behind a corporate proxy or firewall, verify WebSocket connections are allowed. Some networks block WebSockets entirely.
- If your app is served over HTTPS, your Whisp base URL must be HTTPS too — browsers block mixed-content WebSockets.
“401 Unauthorized” loops
Symptom: Every request fails with 401, even after a successful sign-in.
Likely cause: Your refresh token expired or was revoked (e.g. from a logout() on another device). The SDK tried to refresh silently, the refresh failed, and now it’s out of options.
Fix: Clear your stored auth state and re-authenticate the user (show the login screen again).
whisp.realtime.disconnect();
// have the user sign in again → whisp.setAuth({...})
“API key is required for this endpoint”
Symptom: Calling registerUser() or signIn() throws with this message.
Cause: You constructed WhispClient without an apiKey. Those two endpoints always require one.
Fix: If you’re in Node.js, pass apiKey: process.env.WHISP_API_KEY. If you’re in a browser, you shouldn’t be calling these endpoints at all — move them to your backend and use setAuth() on the browser side. See Browser Quickstart.
Missing messages after reconnecting
Realtime is for immediate updates. If the client was offline for a while, you will have missed events during that window. After reconnect, call REST to backfill:
const { messages } = await whisp.getMessages(chatId, 50);
For older history, use cursor-based pagination — see Messages.
Reaction deletion confusion
There are two places you might see a “reaction id” and it’s easy to grab the wrong one.
- In the realtime
reactionevent: the fieldmessageIdis actually the reaction id — pass it toremoveReaction(). - In REST message history: it lives at
messages[].reactions[].reactionId.
Multiple devices / duplicate events
A single user can have multiple simultaneous connections (phone + desktop + another tab). Each connection will receive the same events. Design your UI to dedupe by messageId / reactionId if you render from the realtime stream directly.
Still stuck?
- Re-read the Browser Quickstart or Node.js Quickstart end-to-end — the issue is often a missing step.
- Check the Errors & Retries page for how
WhispErrorsurfaces API-level issues. - File an issue at github.com/whispchat-com with a minimal reproduction.