Error Handling

Learn how to handle errors and edge cases when using the Finatic SDK.

Understanding how to handle errors is crucial for building robust applications with Finatic. This guide covers error handling patterns, common error types, and best practices.

Note: All Finatic methods return a standard response format. Familiarize yourself with the response structure before diving into error handling.

Error Response Structure

When an error occurs, the response looks like this:

1{ 2success: null, 3error: { 4message: "Error description", 5code?: "ERROR_CODE", 6status?: 400, 7details?: { /* additional error details */ } 8}, 9warning: null 10} 11

The error object contains:

  • message: Human-readable error description (always present)
  • code (optional): Machine-readable error code for programmatic handling
  • status (optional): HTTP status code (401, 404, 500, etc.)
  • details (optional): Additional context (validation errors, affected fields, etc.)

Basic Error Handling

Always check for errors before accessing data. Here's an example using listAccounts():

1const result = await finatic.v1.listAccounts(); 2

Then handle the response:

1// TypeScript 2if (result.success) { 3// Handle success 4const accounts = result.success.data; 5console.log('Accounts:', accounts); 6} else if (result.error) { 7// Handle error 8console.error('Error:', result.error.message); 9console.error('Code:', result.error.code); 10console.error('Status:', result.error.status); 11} 12
1# Python 2if result.success: 3# Handle success 4accounts = result.success['data'] 5print(f"Accounts: {accounts}") 6elif result.error: 7# Handle error 8print(f"Error: {result.error['message']}") 9print(f"Code: {result.error.get('code')}") 10print(f"Status: {result.error.get('status')}") 11

Error Types

Authentication Errors

Occur when authentication fails or tokens expire:

1const result = await finatic.v1.listAccounts(); 2 3if (result.error?.code === 'AUTH_ERROR' || result.error?.status === 401) { 4// Token expired or invalid 5// Re-initialize the SDK or refresh the token 6const newFinatic = await FinaticConnect.init(newToken); 7} 8

Common causes:

  • Expired one-time token (Client SDK)
  • Invalid API key (Server SDK)
  • Session expired

Solution:

  • Client SDK: Get a new one-time token from your backend
  • Server SDK: Verify API key is correct and active

Validation Errors

Occur when request parameters are invalid:

1const result = await finatic.v1.listOrders({ accountId: 'your-account-id' }); 2 3if (result.error?.status === 422) { 4// Validation error 5console.error('Validation failed:', result.error.message); 6console.error('Details:', result.error.details); 7} 8

Common causes:

  • Invalid parameter format
  • Missing required parameters
  • Parameter out of range

Solution:

  • Check parameter types and formats
  • Verify all required parameters are provided
  • Review the API reference for parameter requirements

Not Found Errors

Occur when requested resources don't exist:

1const result = await finatic.getCompany({ 2companyId: 'non-existent-id' 3}); 4 5if (result.error?.status === 404) { 6// Resource not found 7console.error('Company not found'); 8} 9

Common causes:

  • Invalid resource ID
  • Resource was deleted
  • Insufficient permissions

Solution:

  • Verify the resource ID is correct
  • Check user permissions
  • Handle gracefully in your UI

Rate Limit Errors

Occur when API rate limits are exceeded:

1const result = await finatic.v1.listAccounts(); 2 3if (result.error?.status === 429) { 4// Rate limited 5const retryAfter = result.error.details?.retry_after; 6console.log(`Rate limited. Retry after ${retryAfter} seconds`); 7 8// Implement exponential backoff 9await new Promise(resolve => setTimeout(resolve, retryAfter * 1000)); 10// Retry the request 11} 12

Solution:

  • Implement exponential backoff
  • Respect Retry-After headers
  • Consider upgrading your subscription tier

Network Errors

Occur when network requests fail:

1try { 2const result = await finatic.v1.listAccounts(); 3} catch (error) { 4// Network error (not an API error) 5if (error instanceof TypeError && error.message.includes('fetch')) { 6console.error('Network error:', error.message); 7// Show user-friendly message 8// Retry with exponential backoff 9} 10} 11

Common causes:

  • No internet connection
  • API server unreachable
  • Timeout

Solution:

  • Check network connectivity
  • Verify baseUrl is correct
  • Implement retry logic with timeouts

Error Handling Patterns

Helper Function

Create a reusable error handler:

1function handleFinaticError(result: FinaticResponse<any>) { 2 if (result.success) { 3 return { success: true, data: result.success.data }; 4 } 5 6 if (result.error) { 7 const { message, code, status } = result.error; 8 9 // Log error 10 console.error(`Finatic Error [${code || status}]:`, message); 11 12 // Handle specific error types 13 switch (status) { 14 case 401: 15 return { success: false, error: 'Authentication failed. Please reconnect.' }; 16 case 404: 17 return { success: false, error: 'Resource not found.' }; 18 case 429: 19 return { success: false, error: 'Rate limit exceeded. Please try again later.' }; 20 default: 21 return { success: false, error: message || 'An error occurred.' }; 22 } 23 } 24 25 return { success: false, error: 'Unknown error occurred.' }; 26 } 27 28 // Usage 29 const result = await finatic.v1.listAccounts(); 30 const handled = handleFinaticError(result); 31

Try-Catch for Network Errors

Wrap SDK calls in try-catch for network errors:

1async function getAccountsSafely() { 2try { 3const result = await finatic.v1.listAccounts(); 4 5if (result.error) { 6// API returned an error response 7throw new Error(result.error.message); 8} 9 10return result.success?.data || []; 11} catch (error) { 12// Network error or other exception 13console.error('Failed to get accounts:', error); 14throw error; 15} 16} 17

Retry Logic

Implement retry logic for transient errors:

1async function getAccountsWithRetry(maxRetries = 3) { 2for (let i = 0; i < maxRetries; i++) { try { const result=await finatic.v1.listAccounts(); if (result.success) { 3 return result.success.data; } // Don't retry on client errors (4xx) if (result.error?.status && result.error.status 4 < 500) { throw new Error(result.error.message); } // Retry on server errors (5xx) or network errors if (i < 5 maxRetries - 1) { await new Promise(resolve=> setTimeout(resolve, Math.pow(2, i) * 1000)); 6 continue; 7 } 8 9 throw new Error(result.error?.message || 'Request failed'); 10 } catch (error) { 11 if (i === maxRetries - 1) throw error; 12 await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000)); 13 } 14 } 15 } 16 ``` 17 18 ## Warning Messages 19 20 Some responses may include warnings: 21 22 ```typescript 23 const result = await finatic.v1.listAccounts(); 24 25 if (result.warning && result.warning.length > 0) { 26 result.warning.forEach(warning => { 27 console.warn('Warning:', warning.message); 28 // Handle warnings (e.g., show to user, log) 29 }); 30 } 31 ``` 32 33 Warnings don't indicate failure but may provide important information about: 34 - Deprecated features 35 - Rate limit approaching 36 - Data freshness 37 - Partial results 38 39 ## Best Practices 40 41 1. **Always check for errors** - Never assume a request succeeded 42 2. **Provide user-friendly messages** - Translate technical errors to user-friendly language 43 3. **Log errors appropriately** - Log full error details for debugging, show simplified messages to users 44 4. **Handle edge cases** - Account for network failures, timeouts, and unexpected responses 45 5. **Implement retry logic** - For transient errors (network, rate limits) 46 6. **Don't retry on client errors** - 4xx errors won't succeed on retry 47 7. **Respect rate limits** - Implement backoff and respect `Retry-After` headers 48 49 ## Common Error Scenarios 50 51 ### Session Not Initialized 52 53 ```typescript 54 // Error: "Session not initialized" 55 // Solution: Ensure SDK is initialized with init() 56 const finatic = await FinaticConnect.init(oneTimeToken); 57 ``` 58 59 ### Invalid Token 60 61 ```typescript 62 // Error: "Invalid token" or 401 status 63 // Solution: Get a new one-time token from your backend 64 const newToken = await fetch('/api/get-token').then(r => r.json()); 65 const finatic = await FinaticConnect.init(newToken.token); 66 ``` 67 68 ### No Broker Connections 69 70 ```typescript 71 // Error: "No broker connections found" 72 // Solution: User needs to connect a broker first 73 await finatic.openPortal({ mode: 'dark' }); 74 ``` 75 76 ## Next Steps 77 78 1. **[Standard Response Object](/docs/quick-start/standard-response-object)** - Review the response format in 79 detail. 80 2. **[Getting Data](/docs/quick-start/getting-data)** - Learn how to retrieve accounts, orders, and positions. 81 3. **[Connecting Brokers](/docs/quick-start/connecting-brokers)** - Learn how to connect broker accounts. 82 4. **[API Reference](/docs/api-reference)** - See all available methods and their error responses.