Welcome!
What did you do?
-
Connect a WhatsApp Baileys instance and let it accumulate some message history (the bug appears to need _count.Message > 0).
-
Call DELETE /instance/logout/{instanceName} with a valid apikey header:
curl -X DELETE -H "apikey: $KEY" "$EVOLUTION_API_URL/instance/logout/suporte"
What did you expect?
HTTP 200 with the documented logout success body:
{"status": "SUCCESS", "error": false, "response": {"message": "Instance logged out"}}
What did you observe instead of what you expected?
HTTP 500 with a PrismaClientKnownRequestError on messageUpdate.create() in the post-logout cleanup path. The Baileys session does close — the next connectionState call returns state: "close" — but the HTTP-level error makes downstream clients believe the operation failed.
Full response body:
{
"status": 500,
"error": "Internal Server Error",
"response": {
"message": [
"PrismaClientKnownRequestError: \nInvalid `this.prismaRepository.messageUpdate.create()` invocation in\n/evolution/dist/main.js:250:5832\n\n 247 WHERE \"instanceId\" = ${this.instanceId}\n 248 AND \"key\"->>'id' = ${S}\n 249 LIMIT 1\n→ 250 `)[0]||null,!m?.id){this.logger.warn(`Original message not found for update. Skipping. Key: ${JSON.stringify(i)}`);continue}u.messageId=m.id}if(n.message===null&&n.status===void 0){this.sendDataWebhook(\"messages.delete\",{...i,status:\"DELETED\"}),this.configService.get(\"DATABASE\").SAVE_DATA.MESSAGE_UPDATE&&await this.prismaRepository.messageUpdate.create(\nAn operation failed because it depends on one or more records that were required but not found. No record was found for a delete."
]
}
}
Immediately after the 500, connectionState confirms the logout actually happened:
{"instance":{"instanceName":"suporte","state":"close"}}
Also worth noting: connectionStatus in fetchInstances does not flip from "open" even after this — it stays "open" indefinitely while disconnectionReasonCode and disconnectionAt are populated. So clients relying on connectionStatus (or anything that reads through it) end up with stale state.
Screenshots/Videos
No response
Which version of the API are you using?
evoapicloud/evolution-api:v2.3.7 (Docker, latest stable tag as of 2026-05-26)
What is your environment?
Docker
Other environment specifications
- Image:
evoapicloud/evolution-api:v2.3.7 (Docker)
- Hosting: Linux container (EasyPanel)
- Integration:
WHATSAPP-BAILEYS
DATABASE_SAVE_DATA_MESSAGE_UPDATE: enabled (default)
- Database: Postgres via Prisma
If applicable, paste the log output
PrismaClientKnownRequestError:
Invalid `this.prismaRepository.messageUpdate.create()` invocation in
/evolution/dist/main.js:250:5832
247 WHERE "instanceId" = ${this.instanceId}
248 AND "key"->>'id' = ${S}
249 LIMIT 1
→ 250 `)[0]||null,!m?.id){...await this.prismaRepository.messageUpdate.create(...)
An operation failed because it depends on one or more records that were required but not found. No record was found for a delete.
Additional Notes
Workaround we adopted (TypeScript client):
try {
return await evolutionFetch(`/instance/logout/${name}`, { method: "DELETE" });
} catch (err) {
const state = await getInstanceStatus(name).catch(() => null);
if (state?.instance?.state && state.instance.state !== "open") {
return { status: "SUCCESS", recoveredFrom: "evolution-500" };
}
throw err;
}
Related issues (same code path, different symptoms; both closed as "not planned"):
These three issues seem to share the same root cause: messageUpdate.create() in whatsapp.baileys.service.ts doesn't defensively handle all the edge cases that can legitimately fire it (message edits with no parent, logout-time cleanup, undefined remoteJid, etc.). Suggestions:
- Guard the
messageUpdate.create() call with the same !m?.id check that the surrounding logger.warn already uses.
- At minimum, don't propagate the cleanup error as an HTTP 500 — the logout succeeded; the response should reflect that. Wrapping the
messageUpdate.create() block in its own try/catch would prevent the secondary failure from masking the primary success.
Welcome!
What did you do?
Connect a WhatsApp Baileys instance and let it accumulate some message history (the bug appears to need
_count.Message > 0).Call
DELETE /instance/logout/{instanceName}with a validapikeyheader:curl -X DELETE -H "apikey: $KEY" "$EVOLUTION_API_URL/instance/logout/suporte"
What did you expect?
HTTP 200 with the documented logout success body:
What did you observe instead of what you expected?
HTTP 500 with a
PrismaClientKnownRequestErroronmessageUpdate.create()in the post-logout cleanup path. The Baileys session does close — the nextconnectionStatecall returnsstate: "close"— but the HTTP-level error makes downstream clients believe the operation failed.Full response body:
Immediately after the 500,
connectionStateconfirms the logout actually happened:Also worth noting:
connectionStatusinfetchInstancesdoes not flip from"open"even after this — it stays"open"indefinitely whiledisconnectionReasonCodeanddisconnectionAtare populated. So clients relying onconnectionStatus(or anything that reads through it) end up with stale state.Screenshots/Videos
No response
Which version of the API are you using?
evoapicloud/evolution-api:v2.3.7(Docker, latest stable tag as of 2026-05-26)What is your environment?
Docker
Other environment specifications
evoapicloud/evolution-api:v2.3.7(Docker)WHATSAPP-BAILEYSDATABASE_SAVE_DATA_MESSAGE_UPDATE: enabled (default)If applicable, paste the log output
Additional Notes
Workaround we adopted (TypeScript client):
Related issues (same code path, different symptoms; both closed as "not planned"):
Missing messageId in MessageUpdate creation(v2.3.4) —PrismaClientValidationErrorremoteJidis missing #2279 —Argument remoteJid is missing(v2.3.6) —PrismaClientValidationErroron null message + undefined statusThese three issues seem to share the same root cause:
messageUpdate.create()inwhatsapp.baileys.service.tsdoesn't defensively handle all the edge cases that can legitimately fire it (message edits with no parent, logout-time cleanup, undefinedremoteJid, etc.). Suggestions:messageUpdate.create()call with the same!m?.idcheck that the surroundinglogger.warnalready uses.messageUpdate.create()block in its own try/catch would prevent the secondary failure from masking the primary success.