From 0c1ab807d2ed5ad6f55b9f8dd7b13f2427b1445d Mon Sep 17 00:00:00 2001 From: MatheusMartinho Date: Thu, 13 Aug 2026 20:20:08 -0300 Subject: [PATCH 1/2] fix(meta): guard non-string mimetype before image check (fixes #2678) mimeTypes.lookup() returns `false`, not `undefined`, when it cannot resolve a type, e.g. a Chatwoot ActiveStorage audio URL with no file extension. Optional chaining only short-circuits on null/undefined, so `false?.startsWith('image/')` threw "TypeError: mimetype?.startsWith is not a function" in sendMessageWithTyping() before the request reached Meta. Check `typeof === 'string'` before calling startsWith; behavior for string mimetypes is unchanged. --- .../integrations/channel/meta/whatsapp.business.service.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/api/integrations/channel/meta/whatsapp.business.service.ts b/src/api/integrations/channel/meta/whatsapp.business.service.ts index 098654c2d0..e554fe4874 100644 --- a/src/api/integrations/channel/meta/whatsapp.business.service.ts +++ b/src/api/integrations/channel/meta/whatsapp.business.service.ts @@ -1125,7 +1125,10 @@ export class BusinessStartupService extends ChannelStartupService { return await this.post(content, 'messages'); } if (message['media']) { - const isImage = message['mimetype']?.startsWith('image/'); + // `mimeTypes.lookup()` returns `false`, not `undefined`, when it cannot resolve the + // type, for example a Chatwoot ActiveStorage URL with no file extension. Optional + // chaining only guards `null` and `undefined`, so `false.startsWith` would throw. + const isImage = typeof message['mimetype'] === 'string' && message['mimetype'].startsWith('image/'); content = { messaging_product: 'whatsapp', From 7336c3b3253bc5d27e9c838d2b717dea714dc031 Mon Sep 17 00:00:00 2001 From: MatheusMartinho Date: Thu, 13 Aug 2026 20:27:22 -0300 Subject: [PATCH 2/2] docs(meta): trim the mimetype guard comment to the mechanism --- .../integrations/channel/meta/whatsapp.business.service.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/api/integrations/channel/meta/whatsapp.business.service.ts b/src/api/integrations/channel/meta/whatsapp.business.service.ts index e554fe4874..eec376b1ed 100644 --- a/src/api/integrations/channel/meta/whatsapp.business.service.ts +++ b/src/api/integrations/channel/meta/whatsapp.business.service.ts @@ -1125,9 +1125,8 @@ export class BusinessStartupService extends ChannelStartupService { return await this.post(content, 'messages'); } if (message['media']) { - // `mimeTypes.lookup()` returns `false`, not `undefined`, when it cannot resolve the - // type, for example a Chatwoot ActiveStorage URL with no file extension. Optional - // chaining only guards `null` and `undefined`, so `false.startsWith` would throw. + // `mimeTypes.lookup()` returns `false`, not `undefined`, when the URL has no file + // extension, and optional chaining only guards `null` and `undefined`. const isImage = typeof message['mimetype'] === 'string' && message['mimetype'].startsWith('image/'); content = {