What a 409 really means, why retrying never fixes it, and how to reconnect without changing a line of code.
Every WhatsApp integration hits this eventually. Handling it properly is the difference between a five-minute fix and a queue full of failures nobody noticed.
A number that has dropped, on the Instances screen
2
Press Show QR on that number
The button on each row reads Show QR while the number is down, and Reconnect while it is up. It is there either way — the stored status is a cache and it can be wrong, so pressing it on a number that only looks connected is the honest way to check. A fresh QR appears if, and only if, the number really is disconnected.
A fresh pairing QR on the existing number — the instance_id does not change
3
Scan with the same phone
WhatsApp → Settings → Linked devices → Link a device.
4
Done
The status returns to connected and sending resumes immediately.
Re-scanning a number you already used today costs nothing extra. Charging is per number per day, so checking a number that turns out to be fine, or repairing one that is not, is free either way.
Nothing in your code changes. The instance_id is the same. The API key is the same. No redeploy, no configuration update, no new number to tell your customers about.
Do not delete the number and create a new one. A new instance gets a new instance_id, which means editing your configuration and deploying — for a problem a 30-second re-scan solves. Reconnecting the existing instance keeps everything as it is.
Do not retry the send in a loop. A 409 cannot succeed until a human scans a QR. A retry loop just burns your rate limit and fills your logs while the real problem sits unnoticed.
Treat 409 instance_not_connected as pause and alert, not as a transient error.
Node.js
async function sendMessage(body) { const res = await fetch("https://api.bulkneo.com/v1/messages/text", { method: "POST", headers: { apikey: process.env.BULKNEO_API_KEY, "Content-Type": "application/json", }, body: JSON.stringify(body), }); if (res.ok) return (await res.json()).data; const { error } = await res.json(); if (error.code === "instance_not_connected") { await pauseQueue(body.instance_id); // stop sending on this number await alertOps("WhatsApp number disconnected — someone needs to re-scan the QR"); await parkForLater(body); // do NOT drop the message return null; } throw new Error(`${error.code}: ${error.message}`);}
Three things that matter in that snippet:
Pause the number, not the whole system — your other numbers are unaffected.
Alert a person. Nothing else will fix this.
Keep the message. Once the number is back, send it. A dropped connection should not mean a lost order confirmation.
Put the connected flag on an internal dashboard, or run a five-minute cron that alerts when it flips to false. Most teams discover a disconnect from a customer complaint; you can discover it from a Slack message instead.
Use a dedicated phone or number for the integration, ideally one that stays charged, online and out of everyday use.
Do not clear linked devices on that phone as part of routine housekeeping.
Watch how many devices are linked. WhatsApp caps them, and adding a new one can evict yours.
The same number on two of your instances is refused. You get 409 number_already_connected, and the session that was already running keeps working — that is deliberate, so a stray second scan can never knock a working number offline.