All Docs
FeaturesAgentOS WorkUpdated March 11, 2026

Fixing Silent SMS Delivery Failures in the Notification Queue

Fixing Silent SMS Delivery Failures in the Notification Queue

Release: v1.0.25 · File: src/inngest/functions/notification-queue.ts

Background

The platform's notification queue supports multiple delivery channels — including email and SMS — routed through the notificationSend Inngest function. SMS delivery is handled by calling sendSms(), which internally uses Twilio to dispatch messages to a recipient's phone number.

The Bug

A stub left over from development meant that, for any notification whose delivery channel included sms, the code was passing recipient.email as the To argument to sendSms() rather than the recipient's actual phone number.

// BEFORE (buggy — line ~180)
if (channel === 'sms') {
  // phone number would come from employee record in production
  await sendSms({ to: recipient.email, body: message });
}

Twilio validates phone numbers in E.164 format. An email address trivially fails this check, so every SMS Twilio received was rejected. Critically, the rejection was silent — no exception was re-thrown and no failed delivery was logged — so operators had no visibility into the problem.

Impact

  • All SMS notifications failed for any notification type that included sms as a delivery channel.
  • Failures produced no log entries, making the issue invisible in dashboards and alerting pipelines.
  • Affected all tenants; severity was proportional to how heavily each tenant relied on SMS-based notification workflows (e.g. shift reminders, payroll alerts, contract approval nudges).

The Fix

The notificationSend function was updated to perform a proper employee record lookup before attempting SMS delivery:

  1. Look up the employee record linked to the notification recipient via employees.userId.
  2. Read the phone number from the employee record.
  3. Call sendSms() with the resolved phone number if one exists.
  4. Record a failed delivery log entry if no phone number is on file, instead of silently no-oping or throwing an unhandled error.
// AFTER (fixed)
if (channel === 'sms') {
  const employee = await db.query.employees.findFirst({
    where: eq(employees.userId, recipient.userId),
  });

  if (!employee?.phone) {
    await logDelivery({ notificationId, channel: 'sms', status: 'failed', reason: 'no_phone_on_file' });
    return;
  }

  await sendSms({ to: employee.phone, body: message });
}

Ensuring Employees Have Phone Numbers on File

With this fix in place, SMS delivery now depends on the employee record containing a valid phone number. To avoid failed delivery log entries:

  • Prompt employees to add a phone number during onboarding or profile completion.
  • Use the HR module's bulk employee import to include phone numbers from your existing directory.
  • Review delivery logs for reason: 'no_phone_on_file' to identify accounts that need updating.

Delivery Log Reference

Failed SMS deliveries are recorded with the following shape:

FieldValue
channelsms
statusfailed
reasonno_phone_on_file

These entries appear in the Notification Delivery Logs section of the admin console and are queryable via the audit log API.