> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usesendly.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Handling

> How to handle errors in the Sendly SDK

## Common Errors

The Sendly SDK throws structured errors that you can catch and handle:

```javascript theme={null}
import { Sendly, SendlyError } from '@sendlyapp/sdk'

try {
  await client.emails.send({
    from: 'noreply@invalid-domain.com',
    to: 'user@example.com',
    subject: 'Email',
    html: '<p>Content</p>'
  })
} catch (error) {
  if (error instanceof SendlyError) {
    console.error(`Status: ${error.status}`)
    console.error(`Code: ${error.code}`)
    console.error(`Message: ${error.message}`)
  } else {
    console.error('Unexpected error:', error)
  }
}
```

## Common Error Codes

### `INVALID_EMAIL` (400)

The provided email is not valid.

```javascript theme={null}
// This will throw an error
await client.emails.send({
  from: 'invalid-email',
  to: 'user@example.com'
})
```

**Solution**: Validate the email format before sending.

***

### `INVALID_DOMAIN` (400)

The sending domain is not verified or does not exist.

```javascript theme={null}
// This fails if the domain is not verified
await client.emails.send({
  from: 'noreply@unverified-domain.com',
  to: 'user@example.com'
})
```

**Solution**:

1. Verify that the domain exists
2. Configure the DNS records
3. Mark the domain as verified

***

### `DOMAIN_NOT_FOUND` (404)

The domain you are trying to access does not exist.

```javascript theme={null}
const domain = await client.domains.get('nonexistent_domain')
// Throws DOMAIN_NOT_FOUND
```

**Solution**: Check the domain ID with `client.domains.list()`

***

### `AUTHENTICATION_ERROR` (401)

The API key is invalid or has expired.

```javascript theme={null}
const client = new Sendly('invalid_key')
// Will throw AUTHENTICATION_ERROR on any request
```

**Solution**: Verify your API key in the dashboard.

***

### `RATE_LIMIT_EXCEEDED` (429)

You have exceeded the request limit.

```javascript theme={null}
// Too many requests in a short time
for (let i = 0; i < 2000; i++) {
  await client.emails.send({...})
}
```

**Solution**:

* Wait before sending more requests
* Implement exponential backoff retries
* Use a processing queue

***

### `SERVER_ERROR` (500)

Internal server error.

**Solution**: Retry after a few seconds.

***

## Error Structure

```typescript theme={null}
interface SendlyError extends Error {
  status: number    // HTTP status code (400, 401, 404, etc.)
  code: string      // Error code
  message: string   // Error description
}
```

## Automatic Retries

Implement retry logic for temporary errors:

```javascript theme={null}
async function sendEmailWithRetry(payload, maxRetries = 3) {
  let lastError;

  for (let i = 0; i < maxRetries; i++) {
    try {
      return await client.emails.send(payload)
    } catch (error) {
      lastError = error
      if (error instanceof SendlyError) {
        // Only retry on temporary errors
        if ([429, 500, 502, 503].includes(error.status)) {
          const delay = Math.pow(2, i) * 1000 // Exponential
          await new Promise(r => setTimeout(r, delay))
        } else {
          throw error // Do not retry permanent errors
        }
      }
    }
  }

  throw lastError
}
```

## Pre-validation

Validate data before sending to avoid errors:

```javascript theme={null}
function validateEmail(email) {
  const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
  return re.test(email)
}

function validateDomain(domain) {
  return domain && domain.includes('.')
}

if (!validateEmail(to) || !validateDomain(from.split('@')[1])) {
  throw new Error('Invalid email or domain')
}

await client.emails.send({ from, to, ... })
```

## Error Logging

Log errors for debugging and monitoring:

```javascript theme={null}
import { Sendly, SendlyError } from '@sendlyapp/sdk'

const client = new Sendly()

async function sendEmail(payload) {
  try {
    return await client.emails.send(payload)
  } catch (error) {
    if (error instanceof SendlyError) {
      console.error('Sendly error:', {
        status: error.status,
        code: error.code,
        message: error.message,
        timestamp: new Date().toISOString()
      })
    }
    throw error
  }
}
```

## Handling by Error Type

```javascript theme={null}
try {
  await client.emails.send({...})
} catch (error) {
  if (error instanceof SendlyError) {
    switch (error.status) {
      case 400:
        console.error('Invalid request:', error.code)
        break
      case 401:
        console.error('Unauthenticated - check your API key')
        break
      case 404:
        console.error('Resource not found:', error.code)
        break
      case 429:
        console.error('Request limit reached')
        break
      case 500:
        console.error('Server error - retrying...')
        break
      default:
        console.error('Unknown error:', error.message)
    }
  }
}
```

## Support

Need help with a specific error? Contact [support@usesendly.app](mailto:support@usesendly.app) with:

* Error code
* Error timestamp
* Context (what you were trying to do)
* Your API key (for debugging)
