Skip to main content
The Bloque SDK provides a comprehensive error handling system with specific error types for different failure scenarios. All errors extend the base BloqueAPIError class.

Error Hierarchy

All SDK errors inherit from BloqueAPIError, which provides common properties for debugging and logging:
interface BloqueAPIError extends Error {
  message: string;         // Human-readable error message
  status?: number;         // HTTP status code (e.g., 400, 401, 500)
  code?: string;           // Error code from API (e.g., 'INVALID_ALIAS')
  requestId?: string;      // Request ID for tracing
  timestamp: Date;         // When the error occurred
  response?: unknown;      // Original response body for debugging
  cause?: Error;          // Underlying error (e.g., network error)
  toJSON(): object;       // JSON representation for logging
}

Error Types

BloqueAPIError

Base error class for all Bloque API errors. Thrown when the API returns an error response or when a network/timeout error occurs.
import { BloqueAPIError } from '@bloque/sdk-core';

try {
  await sdk.accounts.virtual.create({ currency: 'USD' });
} catch (error) {
  if (error instanceof BloqueAPIError) {
    console.error('API Error:', {
      message: error.message,
      status: error.status,
      code: error.code,
      requestId: error.requestId,
      timestamp: error.timestamp
    });
  }
}

BloqueValidationError

Thrown when request validation fails (HTTP 400). Common causes:
  • Missing required fields
  • Invalid field format
  • Invalid field values
  • Business rule validation failures
import { BloqueValidationError } from '@bloque/sdk-core';

try {
  await sdk.accounts.virtual.create({
    currency: 'INVALID' // Invalid currency code
  });
} catch (error) {
  if (error instanceof BloqueValidationError) {
    console.error('Validation failed:', error.message);
    
    // Access field-specific validation errors if available
    if (error.validationErrors) {
      Object.entries(error.validationErrors).forEach(([field, errors]) => {
        console.error(`${field}:`, errors.join(', '));
      });
    }
  }
}
validationErrors
Record<string, string[]>
Validation errors grouped by field (if provided by API)

BloqueAuthenticationError

Thrown when authentication fails (HTTP 401 or 403). Common causes:
  • Invalid or expired API key
  • Invalid or expired JWT token
  • Insufficient permissions for the requested operation
import { BloqueAuthenticationError } from '@bloque/sdk-core';

try {
  const session = await sdk.connect('[email protected]');
} catch (error) {
  if (error instanceof BloqueAuthenticationError) {
    console.error('Authentication failed:', error.message);
    
    // Redirect to login or refresh token
    if (error.status === 401) {
      // Token expired - refresh or re-authenticate
      redirectToLogin();
    } else if (error.status === 403) {
      // Insufficient permissions
      showPermissionError();
    }
  }
}

BloqueNotFoundError

Thrown when a resource is not found (HTTP 404). Common causes:
  • Invalid resource ID
  • Resource was deleted
  • User doesn’t have access to the resource
import { BloqueNotFoundError } from '@bloque/sdk-core';

try {
  await session.accounts.virtual.get('acc_nonexistent');
} catch (error) {
  if (error instanceof BloqueNotFoundError) {
    console.error('Resource not found:', {
      type: error.resourceType,     // e.g., 'account'
      id: error.resourceId,          // e.g., 'acc_nonexistent'
      message: error.message
    });
  }
}
resourceType
string
Type of resource that was not found (e.g., ‘identity’, ‘account’)
resourceId
string
ID of the resource that was not found

BloqueRateLimitError

Thrown when the API rate limit is exceeded (HTTP 429).
The SDK automatically retries rate-limited requests if retry is enabled. This error is only thrown after all retry attempts are exhausted.
import { BloqueRateLimitError } from '@bloque/sdk-core';

try {
  await sdk.accounts.virtual.create({ currency: 'USD' });
} catch (error) {
  if (error instanceof BloqueRateLimitError) {
    console.error('Rate limit exceeded');
    
    // Check when to retry
    if (error.retryAfter) {
      console.log(`Retry after ${error.retryAfter} seconds`);
      setTimeout(() => {
        // Retry the operation
      }, error.retryAfter * 1000);
    }
  }
}
retryAfter
number
Number of seconds to wait before retrying (from Retry-After header)

BloqueInsufficientFundsError

Thrown when an operation requires more funds than available.
import { BloqueInsufficientFundsError } from '@bloque/sdk-core';

try {
  await session.accounts.virtual.transfer({
    from: 'acc_123',
    to: 'acc_456',
    amount: 1000000,
    currency: 'USD'
  });
} catch (error) {
  if (error instanceof BloqueInsufficientFundsError) {
    console.error('Insufficient funds:', {
      requested: error.requestedAmount,
      available: error.availableBalance,
      currency: error.currency
    });
    
    // Show user-friendly message
    alert(`Insufficient balance. You need ${error.requestedAmount} ${error.currency} but only have ${error.availableBalance} ${error.currency}`);
  }
}
requestedAmount
number
Amount requested for the operation
availableBalance
number
Available balance in the account
currency
string
Currency code (e.g., ‘USD’, ‘CLP’)

BloqueNetworkError

Thrown when a network error occurs. Common causes:
  • No internet connection
  • DNS resolution failure
  • Connection refused
  • SSL/TLS errors
import { BloqueNetworkError } from '@bloque/sdk-core';

try {
  await sdk.connect('[email protected]');
} catch (error) {
  if (error instanceof BloqueNetworkError) {
    console.error('Network error:', error.message);
    
    // Show user-friendly message
    alert('Unable to connect. Please check your internet connection.');
    
    // Log underlying cause
    if (error.cause) {
      console.error('Caused by:', error.cause);
    }
  }
}

BloqueTimeoutError

Thrown when a request exceeds the configured timeout duration.
The SDK automatically retries timeout errors if retry is enabled.
import { BloqueTimeoutError } from '@bloque/sdk-core';

try {
  await sdk.accounts.virtual.create({ currency: 'USD' });
} catch (error) {
  if (error instanceof BloqueTimeoutError) {
    console.error(`Request timed out after ${error.timeoutMs}ms`);
    
    // Retry with longer timeout
    // Note: This example is simplified - use proper retry logic
  }
}
timeoutMs
number
Timeout duration in milliseconds that was exceeded

BloqueConfigError

Thrown when the SDK is misconfigured. This error is thrown before making any API requests.
import { BloqueConfigError } from '@bloque/sdk-core';

try {
  const sdk = new SDK({
    mode: 'production',
    baseUrl: 'https://custom.com', // ❌ Cannot use both
    auth: { type: 'apiKey', apiKey: 'key_...' }
  });
} catch (error) {
  if (error instanceof BloqueConfigError) {
    console.error('Configuration error:', error.message);
  }
}

Error Handling Patterns

Type-Safe Error Handling

Use TypeScript’s type narrowing with instanceof to handle specific error types:
import {
  BloqueValidationError,
  BloqueAuthenticationError,
  BloqueNotFoundError,
  BloqueRateLimitError,
  BloqueInsufficientFundsError,
  BloqueNetworkError,
  BloqueTimeoutError,
  BloqueAPIError
} from '@bloque/sdk-core';

try {
  const result = await sdk.accounts.virtual.create({ currency: 'USD' });
} catch (error) {
  if (error instanceof BloqueValidationError) {
    // Handle validation errors
    handleValidationError(error);
  } else if (error instanceof BloqueAuthenticationError) {
    // Handle auth errors
    redirectToLogin();
  } else if (error instanceof BloqueNotFoundError) {
    // Handle not found
    show404Page();
  } else if (error instanceof BloqueRateLimitError) {
    // Handle rate limiting
    showRateLimitMessage(error.retryAfter);
  } else if (error instanceof BloqueInsufficientFundsError) {
    // Handle insufficient funds
    showInsufficientFundsMessage(error);
  } else if (error instanceof BloqueNetworkError) {
    // Handle network errors
    showNetworkError();
  } else if (error instanceof BloqueTimeoutError) {
    // Handle timeouts
    showTimeoutError();
  } else if (error instanceof BloqueAPIError) {
    // Handle other API errors
    showGenericError(error);
  } else {
    // Handle unexpected errors
    console.error('Unexpected error:', error);
  }
}

Global Error Handler

Create a centralized error handler for consistent error handling:
import { BloqueAPIError } from '@bloque/sdk-core';

function handleBloqueError(error: unknown) {
  if (!(error instanceof BloqueAPIError)) {
    console.error('Unexpected error:', error);
    return;
  }
  
  // Log for debugging
  console.error('Bloque API Error:', error.toJSON());
  
  // Track in error monitoring service
  errorMonitoring.captureException(error, {
    extra: {
      requestId: error.requestId,
      code: error.code,
      status: error.status
    }
  });
  
  // Show user-friendly message based on error type
  const message = getUserFriendlyMessage(error);
  showToast(message, 'error');
}

function getUserFriendlyMessage(error: BloqueAPIError): string {
  if (error instanceof BloqueNetworkError) {
    return 'Unable to connect. Please check your internet connection.';
  }
  if (error instanceof BloqueAuthenticationError) {
    return 'Your session has expired. Please log in again.';
  }
  if (error instanceof BloqueValidationError) {
    return error.message; // Validation messages are usually user-friendly
  }
  return 'Something went wrong. Please try again later.';
}

Retry Logic

Implement custom retry logic for specific operations:
import { BloqueTimeoutError, BloqueNetworkError } from '@bloque/sdk-core';

async function retryOperation<T>(
  operation: () => Promise<T>,
  maxRetries = 3,
  delayMs = 1000
): Promise<T> {
  let lastError: Error;
  
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await operation();
    } catch (error) {
      lastError = error as Error;
      
      // Only retry on network or timeout errors
      if (
        error instanceof BloqueNetworkError ||
        error instanceof BloqueTimeoutError
      ) {
        // Exponential backoff
        const delay = delayMs * Math.pow(2, attempt);
        await new Promise(resolve => setTimeout(resolve, delay));
        continue;
      }
      
      // Don't retry other errors
      throw error;
    }
  }
  
  throw lastError!;
}

// Usage
const account = await retryOperation(
  () => sdk.accounts.virtual.create({ currency: 'USD' }),
  3,
  1000
);

Logging and Debugging

All errors include a toJSON() method for structured logging:
import { BloqueAPIError } from '@bloque/sdk-core';

try {
  await sdk.accounts.virtual.create({ currency: 'USD' });
} catch (error) {
  if (error instanceof BloqueAPIError) {
    // Log structured error data
    console.error('API Error:', error.toJSON());
    // Output:
    // {
    //   name: 'BloqueValidationError',
    //   message: 'Invalid currency code',
    //   status: 400,
    //   code: 'INVALID_CURRENCY',
    //   requestId: 'req_abc123',
    //   timestamp: '2024-03-15T10:30:00.000Z',
    //   response: { ... },
    //   stack: '...'
    // }
  }
}

Request Tracing

Use the requestId field to trace requests across your system:
try {
  await sdk.accounts.virtual.create({ currency: 'USD' });
} catch (error) {
  if (error instanceof BloqueAPIError && error.requestId) {
    // Include request ID in logs for support inquiries
    logger.error(`Failed to create account [requestId: ${error.requestId}]`, {
      error: error.toJSON()
    });
  }
}

Best Practices

Always Handle Errors

Never leave await calls without try-catch blocks in production code

Use Type Guards

Use instanceof checks for type-safe error handling

Log Request IDs

Include requestId in error logs for easier debugging

User-Friendly Messages

Convert technical errors to user-friendly messages
Never expose sensitive error details (like API keys or internal implementation details) to end users.

Next Steps

Configuration

Configure timeout and retry settings

Platform Support

Platform-specific error handling

Build docs developers (and LLMs) love