Skip to content

Commit 7e4f4a7

Browse files
author
Bruno Sgarbi
committed
fix(instance.controller): emit remove.instance even when logout fails
When a Baileys WebSocket dies but the in-memory `waInstances[name]` entry still exists (a "zombie" instance), `deleteInstance()` calls `await this.logout()` which throws "Connection Closed". The throw causes the outer try/catch to skip the `eventEmitter.emit('remove.instance')` call — which is the only mechanism that purges the zombie from `waInstances`. Result: zombies persist in memory until the entire `evo2_api` container is restarted, affecting ALL instances on the host (not just the broken one). Operators have no per-instance recovery path in v2.3.x — their only option is `docker restart`, which forces every connected user to re-scan the QR code. Fix: wrap the inner `logout()` call in its own try/catch. Log a warning when it fails but continue to the cleanup emit. The in-memory entry must be removed regardless of whether logout completed cleanly — `remove.instance` is the canonical way to purge a stuck instance, and DB/cache cleanup happens in the same event handler. This makes `DELETE /instance/:name` idempotent against zombies: a caller can always recover a single instance without nuking the whole host. Refs: - #693 (instance/restart closes the session) - #1286 (Connection Closed in v2.2.3) - #2026 (Sync lost after reboot) - #2027 (Loss of synchronization on reboot) Tested in production at Rigarr (14 instances, ~25k msgs/day) by overlaying this patch on v2.3.7 via Docker. Before: any zombie forced a full container restart. After: per-instance cleanup works cleanly while other vendors stay connected. Signed-off-by: Bruno Cavalcante Sgarbi <bcsgarbi@gmail.com>
1 parent cd800f2 commit 7e4f4a7

1 file changed

Lines changed: 12 additions & 1 deletion

File tree

src/api/controllers/instance.controller.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,18 @@ export class InstanceController {
456456
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED) waInstances?.clearCacheChatwoot();
457457

458458
if (instance.state === 'connecting' || instance.state === 'open') {
459-
await this.logout({ instanceName });
459+
try {
460+
await this.logout({ instanceName });
461+
} catch (logoutError) {
462+
// RIGARR PATCH: zombie instance cleanup.
463+
// When a Baileys socket is dead but waInstances[name] still exists,
464+
// logout() throws "Connection Closed". Without this catch, the
465+
// remove.instance emit below never runs, leaving the zombie in memory
466+
// forever (only fixable by restarting the entire container).
467+
this.logger.warn(
468+
`[ZOMBIE-CLEANUP] logout failed for "${instanceName}" (likely zombie socket): ${logoutError?.toString?.() || logoutError}. Proceeding with cleanup.`,
469+
);
470+
}
460471
}
461472

462473
try {

0 commit comments

Comments
 (0)