The "sms_send_failed: Sending SMS failed" error occurs when Supabase Auth cannot send SMS messages for phone authentication or OTP verification. This typically happens due to misconfigured SMS provider settings, rate limiting, invalid phone numbers, or insufficient credits with the SMS service provider.
The "sms_send_failed" error is a Supabase Auth error code that indicates the SMS delivery service failed to send a text message. This error can occur during phone-based authentication flows, password resets via SMS, or multi-factor authentication (MFA) setups. When Supabase attempts to send an SMS for authentication purposes (such as phone sign-in, OTP verification, or MFA enrollment), it relies on an integrated SMS provider. If the SMS provider encounters any issues—whether due to configuration problems, rate limits, invalid recipient numbers, or service outages—the operation fails and returns this error. This error is particularly common in development environments where SMS settings may not be fully configured, or in production when SMS credits have been exhausted or phone number formatting is incorrect.
First, verify that SMS is properly configured in your Supabase project:
1. Go to your Supabase Dashboard → Authentication → Providers
2. Scroll to the "Phone" section
3. Ensure "Enable phone sign-in" is toggled ON
4. Check that you have a valid SMS provider configured (Twilio, MessageBird, etc.)
5. Verify API keys, account SID, and auth tokens are correct and not expired
If using Twilio, ensure your Twilio account has sufficient credits and the phone number is verified for sending SMS.
Ensure phone numbers are in the correct international format:
// Correct format: +[country code][number]
const validNumber = '+14155552671'; // US number
const invalidNumber = '4155552671'; // Missing country code
// In Supabase client:
const { error } = await supabase.auth.signInWithOtp({
phone: '+14155552671', // Must include country code
})Common issues:
- Missing "+" prefix
- No country code (e.g., using local format like "4155552671" instead of "+14155552671")
- Invalid country code
- Number not supported by your SMS provider
SMS providers impose rate limits and require sufficient credits:
1. Check your SMS provider dashboard:
- Twilio: Check "Usage" and "Balance" in Console
- MessageBird: Check "Balance & Top-up" section
- Other providers: Verify account has positive balance
2. Review rate limits:
- Supabase has default rate limits for SMS sending
- SMS providers have their own rate limits per number/account
- Check if you've exceeded daily/monthly SMS quotas
3. For development/testing:
- Use test credentials or sandbox mode if available
- Consider using mock SMS services for development
- Use phone numbers verified in your SMS provider account
Test SMS delivery with a phone number you control and have verified with your SMS provider:
// Test with a known working number
async function testSmsDelivery() {
const { data, error } = await supabase.auth.signInWithOtp({
phone: '+14155552671', // Your verified test number
options: {
channel: 'sms'
}
});
if (error) {
console.error('SMS test failed:', error.message);
// Check error.code for specific error details
if (error.code === 'sms_send_failed') {
console.log('SMS provider configuration issue');
}
} else {
console.log('SMS sent successfully');
}
}If this works but production numbers fail, the issue may be with specific numbers being blocked or unsupported.
Examine detailed error information in Supabase logs:
1. Check Supabase Dashboard logs:
- Go to Project → Authentication → Logs
- Filter for "sms_send_failed" errors
- Look for additional error details or provider-specific error codes
2. Client-side error inspection:
const { error } = await supabase.auth.signInWithOtp({
phone: phoneNumber,
options: { channel: 'sms' }
});
if (error) {
console.error('Full error object:', error);
console.error('Error code:', error.code); // Should be "sms_send_failed"
console.error('Error status:', error.status); // HTTP status code
console.error('Error message:', error.message);
}3. Common associated errors:
- over_sms_send_rate_limit - Too many SMS sent to this number
- validation_failed - Phone number validation failed
- Provider-specific errors from Twilio/MessageBird etc.
As a contingency plan, provide alternative authentication methods:
// Offer email fallback if SMS fails
async function authenticateWithFallback(phoneNumber, email) {
try {
// Try SMS first
const { error } = await supabase.auth.signInWithOtp({
phone: phoneNumber,
options: { channel: 'sms' }
});
if (error && error.code === 'sms_send_failed') {
console.warn('SMS failed, falling back to email');
// Fallback to email OTP
const { error: emailError } = await supabase.auth.signInWithOtp({
email: email
});
if (emailError) {
throw new Error('Both SMS and email failed: ' + emailError.message);
}
return { success: true, method: 'email' };
}
return { success: true, method: 'sms' };
} catch (err) {
console.error('Authentication failed:', err);
return { success: false, error: err.message };
}
}Also consider implementing:
- Magic link authentication as backup
- Social providers (Google, GitHub) as alternatives
- Temporary bypass codes for critical users
## Deep Dive: SMS Provider Integration
Supabase supports multiple SMS providers for authentication:
### Supported Providers
1. Twilio (default/recommended)
- Requires: Account SID, Auth Token, Messaging Service SID or Phone Number
- Best for: Global coverage, high reliability
- Note: Some countries have carrier restrictions
2. MessageBird
- Requires: API key, originator (sender ID)
- Best for: European coverage
3. Custom SMS Provider
- Can integrate via webhooks or custom Edge Functions
- Requires implementing the SMS sending logic yourself
### Carrier and Regional Considerations
- Carrier filtering: Some carriers block short codes or certain message types
- DLC (10DLC) regulations: US requires registration for A2P (application-to-person) messaging
- International restrictions: Some countries prohibit international SMS or require local numbers
- Spam filters: Aggressive spam filtering may block authentication messages
### Monitoring and Alerting
Set up monitoring for SMS delivery rates:
- Track success/failure rates by country/carrier
- Set up alerts for dropping delivery rates
- Monitor credit balances automatically
- Implement circuit breakers for SMS failures
### Cost Optimization
- Use local/in-country numbers when possible (cheaper rates)
- Implement rate limiting to prevent abuse
- Consider using WhatsApp Business API as alternative (often cheaper for international)
- Cache successful authentications to reduce SMS volume
### Security Considerations
- Implement rate limiting to prevent SMS bombing attacks
- Use CAPTCHA for public-facing SMS authentication forms
- Consider time-based restrictions for SMS sending
- Log all SMS attempts for audit purposes
email_conflict_identity_not_deletable: Cannot delete identity because of email conflict
How to fix "Cannot delete identity because of email conflict" in Supabase
mfa_challenge_expired: MFA challenge has expired
How to fix "mfa_challenge_expired: MFA challenge has expired" in Supabase
conflict: Database conflict, usually related to concurrent requests
How to fix "database conflict usually related to concurrent requests" in Supabase
phone_exists: Phone number already exists
How to fix "phone_exists" in Supabase
StorageApiError: resource_already_exists
StorageApiError: Resource already exists