SDK (Beta)Error Handling

Error Handling

All Aerostack SDK methods throw typed errors on failure. This guide covers the error types, how to catch and handle them, and strategies for retrying failed operations.

⚠️

Beta — Error types are stable but new error codes may be added in minor versions.

Error types

The SDK throws specific error classes depending on what went wrong:

Error ClassWhen it occursHTTP Status
ClientErrorInvalid request, missing parameters, bad input400
AuthenticationErrorInvalid or expired token, unauthorized access401
ForbiddenErrorValid token but insufficient permissions403
NotFoundErrorResource does not exist404
ValidationErrorInput fails server-side validation rules422
RateLimitErrorToo many requests429
ServerErrorUnexpected server failure500+
NetworkErrorConnection failed, timeout, DNS failureN/A

Error properties

Every SDK error includes:

interface AerostackError {
  message: string    // Human-readable error description
  code: string       // Machine-readable error code (e.g., 'AUTH_INVALID_TOKEN')
  status: number     // HTTP status code
  details?: any      // Additional context (validation errors, rate limit info)
}

Basic try/catch

import { useAuth } from '@aerostack/react'
 
function LoginForm() {
  const { signIn, error, loading } = useAuth()
 
  const handleSubmit = async (email: string, password: string) => {
    try {
      await signIn(email, password)
      // Success -- user and tokens are set
    } catch (err) {
      // err.message is also reflected in the `error` state
      if (err.code === 'AUTH_INVALID_CREDENTIALS') {
        // Wrong email or password
      } else if (err.code === 'AUTH_ACCOUNT_LOCKED') {
        // Too many failed attempts
      } else if (err.code === 'AUTH_EMAIL_NOT_VERIFIED') {
        // Redirect to verification page
      }
    }
  }
 
  return (
    <div>
      {/* The error state is set automatically by useAuth */}
      {error && <p style={{ color: 'red' }}>{error}</p>}
    </div>
  )
}

Common error codes

Authentication errors

CodeDescription
AUTH_INVALID_CREDENTIALSWrong email or password
AUTH_INVALID_TOKENAccess token is malformed or expired
AUTH_ACCOUNT_LOCKEDAccount locked due to too many failed attempts (60-minute lockout)
AUTH_EMAIL_NOT_VERIFIEDEmail verification required before sign-in
AUTH_USER_NOT_FOUNDNo account with this email
AUTH_EMAIL_ALREADY_EXISTSEmail already registered
AUTH_OTP_EXPIREDOTP code has expired (10-minute window)
AUTH_OTP_INVALIDWrong OTP code
AUTH_REFRESH_TOKEN_INVALIDRefresh token expired or revoked

Database errors

CodeDescription
DB_QUERY_ERRORSQL syntax error or constraint violation
DB_CONSTRAINT_VIOLATIONUnique constraint, foreign key, or NOT NULL violation
DB_TABLE_NOT_FOUNDReferenced table does not exist

Storage errors

CodeDescription
STORAGE_FILE_TOO_LARGEUpload exceeds size limit
STORAGE_FILE_NOT_FOUNDRequested file does not exist
STORAGE_QUOTA_EXCEEDEDStorage quota for the project is full

Rate limit errors

CodeDescription
RATE_LIMIT_EXCEEDEDToo many requests in the time window
AUTH_OTP_VERIFY_LIMITToo many OTP verification attempts (max 3)

Retry strategies

Simple retry with backoff

async function withRetry<T>(
  fn: () => Promise<T>,
  maxRetries = 3,
  baseDelay = 1000
): Promise<T> {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      return await fn()
    } catch (err) {
      // Don't retry client errors (bad input won't fix itself)
      if (err.status >= 400 && err.status < 500 && err.status !== 429) {
        throw err
      }
 
      if (attempt === maxRetries) throw err
 
      // Exponential backoff: 1s, 2s, 4s
      const delay = baseDelay * Math.pow(2, attempt)
      await new Promise(resolve => setTimeout(resolve, delay))
    }
  }
  throw new Error('Unreachable')
}
 
// Usage
const users = await withRetry(() =>
  sdk.db.query('SELECT * FROM users WHERE active = 1')
)

Retry with rate limit awareness

async function withRateLimitRetry<T>(fn: () => Promise<T>): Promise<T> {
  try {
    return await fn()
  } catch (err) {
    if (err.code === 'RATE_LIMIT_EXCEEDED' && err.details?.retryAfter) {
      // Wait the exact time the server tells us
      await new Promise(resolve =>
        setTimeout(resolve, err.details.retryAfter * 1000)
      )
      return await fn()
    }
    throw err
  }
}

Token refresh on auth error

The SDK handles token refresh automatically on 401 responses. For manual handling:

async function authenticatedRequest<T>(fn: () => Promise<T>): Promise<T> {
  try {
    return await fn()
  } catch (err) {
    if (err.code === 'AUTH_INVALID_TOKEN') {
      // Token expired -- refresh and retry
      await refreshAccessToken(tokens.refreshToken)
      return await fn()
    }
    throw err
  }
}

React error boundaries

For unexpected errors, wrap SDK-dependent components in an error boundary:

src/components/ErrorBoundary.tsx
import { Component, ReactNode } from 'react'
 
interface Props {
  children: ReactNode
  fallback: ReactNode
}
 
interface State {
  hasError: boolean
  error: Error | null
}
 
export class SDKErrorBoundary extends Component<Props, State> {
  state: State = { hasError: false, error: null }
 
  static getDerivedStateFromError(error: Error) {
    return { hasError: true, error }
  }
 
  render() {
    if (this.state.hasError) {
      return this.props.fallback
    }
    return this.props.children
  }
}
 
// Usage
<SDKErrorBoundary fallback={<p>Something went wrong. Please reload.</p>}>
  <LiveDashboard />
</SDKErrorBoundary>

Debugging tips

  1. Check the error state — React hooks (useAuth, useDb) set an error string automatically. Display it in your UI during development.

  2. Log error details — The details property often contains field-level validation errors or rate limit retry-after values.

  3. Check the network tab — SDK errors include the HTTP status code and response body. The browser network tab shows the exact request and response.

  4. Enable verbose logging — Set the debug option when initializing the SDK:

const client = new AerostackClient({
  projectId,
  apiKey,
  debug: true, // Logs all requests and responses to console
})
  1. Check the dashboard — Error logs are available in the Aerostack Dashboard under your project’s Logs section.