From a067e5d26017b7ac691d7ac2b40a36cf3d283cc0 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Thu, 25 Jun 2026 19:21:18 -0500 Subject: [PATCH] fix: handle network errors and non-JSON SMS responses as 400 not 500 Catch fetch network errors and non-JSON response bodies to prevent unhandled exceptions from becoming opaque 500s. Co-Authored-By: Claude Sonnet 4.6 --- backend/src/sms/sms.service.ts | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/backend/src/sms/sms.service.ts b/backend/src/sms/sms.service.ts index 61a0501..af97e38 100644 --- a/backend/src/sms/sms.service.ts +++ b/backend/src/sms/sms.service.ts @@ -26,28 +26,36 @@ export class SmsService { async send(numero: string, mensaje: string): Promise<{ ok: boolean; id?: string }> { const config = await this.getConfig(); - if (!config?.api_key) throw new BadRequestException('SMS API key no configurada'); + if (!config?.api_key) { + this.logger.error('SMS API key no configurada en settings'); + throw new BadRequestException('SMS no configurado. Configure la API key en el panel de administración.'); + } - // El proveedor espera el número sin + (ej: 573001234567) const normalizedNumero = numero.startsWith('+') ? numero.slice(1) : numero; - const res = await fetch(SMS_ENDPOINT, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${config.api_key}`, - }, - body: JSON.stringify({ numero: normalizedNumero, mensaje }), - }); + let res: Response; + try { + res = await fetch(SMS_ENDPOINT, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${config.api_key}`, + }, + body: JSON.stringify({ numero: normalizedNumero, mensaje }), + }); + } catch (networkErr) { + this.logger.error(`Error de red al conectar con proveedor SMS: ${networkErr}`); + throw new BadRequestException('No se pudo conectar con el proveedor de SMS. Intenta de nuevo.'); + } if (!res.ok) { const err = await res.json().catch(() => ({ error: res.statusText })); this.logger.error(`SMS error ${res.status}: ${JSON.stringify(err)}`); - throw new BadRequestException(err.error || `Error al enviar SMS: ${res.status}`); + throw new BadRequestException(err?.error || err?.message || `Error al enviar SMS: ${res.status}`); } - const result = await res.json(); - this.logger.log(`SMS enviado a ${numero}`); + const result = await res.json().catch(() => ({ ok: true })); + this.logger.log(`SMS enviado a ${normalizedNumero}`); return result; }