Error Handling

Proper error handling with specific error classes

The SDK provides specific error classes for different failure scenarios, making it easy to handle errors appropriately in your application.

Error Classes

AuthenticationError

Thrown when API authentication fails (HTTP 401).

Common causes: Invalid API key, expired key, or missing key

NotFoundError

Thrown when a requested resource doesn't exist (HTTP 404).

Common causes: Invalid ID, deleted resource, or wrong endpoint

ValidationError

Thrown when request validation fails (HTTP 400).

Common causes: Missing required fields, invalid data types, or schema violations

RateLimitError

Thrown when rate limits are exceeded (HTTP 429).

Common causes: Too many requests in a short time period

GraphQLError

Thrown when GraphQL returns errors.

Common causes: Query syntax errors, resolver failures, or permission issues

NetworkError

Thrown when network requests fail.

Common causes: No internet connection, DNS failures, or timeouts

Import Error Classes

import Prompt Forge, {
  AuthenticationError,
  NotFoundError,
  ValidationError,
  RateLimitError,
  GraphQLError,
  NetworkError,
  Prompt ForgeError  // Base class for all SDK errors
} from '@promptforge/sdk'

Basic Error Handling

import Prompt Forge, { AuthenticationError, NotFoundError } from '@promptforge/sdk'

const client = new Prompt Forge({
  apiKey: process.env.PROMPTFORGE_API_KEY
})

try {
  const result = await client.prompts.execute('prompt-id', {
    topic: 'JavaScript'
  })

  console.log(result.output)

} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Authentication failed - check your API key')
    // Maybe refresh the key or prompt user to login
  } else if (error instanceof NotFoundError) {
    console.error('Prompt not found - check the ID')
    // Maybe show list of available prompts
  } else {
    console.error('Unexpected error:', error.message)
    // Generic error handling
  }
}

Comprehensive Error Handling

import Prompt Forge, {
  AuthenticationError,
  NotFoundError,
  ValidationError,
  RateLimitError,
  GraphQLError,
  NetworkError
} from '@promptforge/sdk'

async function executePromptSafely(promptId, input) {
  try {
    const result = await client.prompts.execute(promptId, input)
    return { success: true, data: result }

  } catch (error) {
    // Authentication errors
    if (error instanceof AuthenticationError) {
      console.error('Authentication failed')
      console.error('Check that your API key is valid and not expired')
      return {
        success: false,
        error: 'authentication_failed',
        message: 'Please check your API credentials',
        retry: false
      }
    }

    // Not found errors
    if (error instanceof NotFoundError) {
      console.error('Resource not found')
      return {
        success: false,
        error: 'not_found',
        message: 'The requested prompt does not exist',
        retry: false
      }
    }

    // Validation errors
    if (error instanceof ValidationError) {
      console.error('Validation failed')
      console.error('Errors:', error.errors)
      return {
        success: false,
        error: 'validation_failed',
        message: 'Input validation failed',
        details: error.errors,
        retry: false
      }
    }

    // Rate limit errors
    if (error instanceof RateLimitError) {
      console.error('Rate limit exceeded')
      console.error('Too many requests - please slow down')
      return {
        success: false,
        error: 'rate_limit',
        message: 'Please wait before trying again',
        retry: true,
        retryAfter: 60  // seconds
      }
    }

    // GraphQL errors
    if (error instanceof GraphQLError) {
      console.error('GraphQL error')
      console.error('Errors:', error.errors)
      return {
        success: false,
        error: 'graphql_error',
        message: error.message,
        details: error.errors,
        retry: false
      }
    }

    // Network errors
    if (error instanceof NetworkError) {
      console.error('Network error')
      console.error('Check your internet connection')
      return {
        success: false,
        error: 'network_error',
        message: 'Network request failed',
        retry: true,
        retryAfter: 5
      }
    }

    // Unknown errors
    console.error('Unknown error:', error)
    return {
      success: false,
      error: 'unknown',
      message: error.message || 'An unexpected error occurred',
      retry: false
    }
  }
}

// Usage
const result = await executePromptSafely('prompt-id', {
  topic: 'AI Ethics'
})

if (result.success) {
  console.log(result.data.output)
} else {
  console.error(`Error: ${result.message}`)
  if (result.retry) {
    console.log(`Retrying in ${result.retryAfter} seconds...`)
  }
}

Retry Logic

Implement automatic retries for transient failures like network errors or rate limits.

import { NetworkError, RateLimitError } from '@promptforge/sdk'

async function executeWithRetry(fn, maxRetries = 3) {
  let lastError

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await fn()
    } catch (error) {
      lastError = error

      // Only retry network errors and rate limits
      const shouldRetry =
        error instanceof NetworkError ||
        error instanceof RateLimitError

      if (!shouldRetry || attempt === maxRetries) {
        throw error
      }

      // Exponential backoff
      const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000)
      console.log(`Attempt ${attempt} failed, retrying in ${delay}ms...`)

      await new Promise(resolve => setTimeout(resolve, delay))
    }
  }

  throw lastError
}

// Usage
try {
  const result = await executeWithRetry(async () => {
    return await client.prompts.execute('prompt-id', {
      topic: 'Resilient Systems'
    })
  })

  console.log(result.output)
} catch (error) {
  console.error('Failed after retries:', error.message)
}

Validation Error Details

ValidationError includes detailed information about what went wrong.

try {
  await client.prompts.create({
    name: '',  // Invalid: empty string
    template: 'Hello {{name}}',
    // Missing required fields
  })
} catch (error) {
  if (error instanceof ValidationError) {
    console.error('Validation failed:')
    error.errors.forEach(err => {
      console.error(`  - ${err.field}: ${err.message}`)
    })

    // Example output:
    // - name: Name is required
    // - provider: Provider is required
    // - model: Model is required
  }
}

Error Logging

Log errors properly for debugging and monitoring.

import { Prompt ForgeError } from '@promptforge/sdk'

function logError(error, context = {}) {
  const errorInfo = {
    timestamp: new Date().toISOString(),
    message: error.message,
    type: error.name,
    ...context
  }

  // Add SDK-specific info
  if (error instanceof Prompt ForgeError) {
    errorInfo.statusCode = error.statusCode
    if (error.errors) {
      errorInfo.details = error.errors
    }
  }

  // Log to your monitoring system
  console.error(JSON.stringify(errorInfo, null, 2))

  // Send to error tracking service
  // Sentry.captureException(error, { extra: errorInfo })
  // Datadog.logger.error(error.message, errorInfo)
}

try {
  const result = await client.prompts.execute('prompt-id', input)
} catch (error) {
  logError(error, {
    operation: 'execute_prompt',
    promptId: 'prompt-id',
    userId: 'user-123'
  })
}

Best Practices

Always Use Try-Catch

All SDK methods that make API calls can throw errors. Always wrap them in try-catch blocks.

Handle Specific Errors

Don't just catch all errors generically. Handle specific error types differently based on whether they're user errors, transient failures, or system errors.

Implement Retries

Retry transient failures like network errors and rate limits with exponential backoff. Don't retry validation or authentication errors.

Log Everything

Log errors with context (operation, input, user ID) to make debugging easier. Use structured logging for better searchability.

User-Friendly Messages

Show user-friendly error messages to end users, but log technical details for debugging.

Complete Example

import Prompt Forge, {
  AuthenticationError,
  ValidationError,
  RateLimitError,
  NetworkError
} from '@promptforge/sdk'

const client = new Prompt Forge({
  apiKey: process.env.PROMPTFORGE_API_KEY
})

async function generateContent(promptId, input) {
  const maxRetries = 3
  let attempt = 0

  while (attempt < maxRetries) {
    try {
      attempt++

      const result = await client.prompts.execute(promptId, input)

      // Success!
      return {
        success: true,
        output: result.output,
        metrics: {
          latency: result.latencyMs,
          cost: result.costUsd,
          tokens: {
            in: result.tokenIn,
            out: result.tokenOut
          }
        }
      }

    } catch (error) {
      // Don't retry these errors
      if (error instanceof AuthenticationError) {
        return {
          success: false,
          error: 'auth_failed',
          userMessage: 'Authentication failed. Please contact support.',
          retry: false
        }
      }

      if (error instanceof ValidationError) {
        return {
          success: false,
          error: 'invalid_input',
          userMessage: 'Please check your input and try again.',
          details: error.errors,
          retry: false
        }
      }

      // Retry these errors
      const shouldRetry =
        (error instanceof NetworkError || error instanceof RateLimitError) &&
        attempt < maxRetries

      if (!shouldRetry) {
        return {
          success: false,
          error: error.name,
          userMessage: 'An error occurred. Please try again later.',
          technicalMessage: error.message,
          retry: false
        }
      }

      // Wait before retrying
      const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000)
      console.log(`Retry ${attempt}/${maxRetries} in ${delay}ms`)
      await new Promise(resolve => setTimeout(resolve, delay))
    }
  }
}

// Usage
const result = await generateContent('prompt-id', {
  topic: 'Error Handling Best Practices'
})

if (result.success) {
  console.log(result.output)
  console.log(`Cost: $${result.metrics.cost}`)
} else {
  console.error(`Error: ${result.userMessage}`)
  if (result.details) {
    console.error('Details:', result.details)
  }
}