> For the complete documentation index, see [llms.txt](https://docs.yield.fi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.yield.fi/earn-with-yieldfi/integration-sdk/error-handling/best-practices.md).

# Best Practices

Follow these best practices for robust error handling in your application.

### Always Use Try-Catch

Wrap SDK calls in try-catch blocks:

```typescript
try {
  const vault = await sdk.vault.getVaultByKey("yusd", 1);
} catch (error) {
  // Handle error
}
```

### Check Error Types

Use `instanceof` to check error types:

```typescript
import {
  AuthenticationError,
  NetworkError,
  ValidationError,
} from "yieldfi-sdk";

try {
  await sdk.auth.login(credentials);
} catch (error) {
  if (error instanceof AuthenticationError) {
    // Handle auth errors
  } else if (error instanceof NetworkError) {
    // Handle network errors
  } else if (error instanceof ValidationError) {
    // Handle validation errors
  }
}
```

### Provide User-Friendly Messages

Translate technical errors to user-friendly messages:

```typescript
function getUserFriendlyError(error: SDKError): string {
  if (error instanceof AuthenticationError) {
    return "Please login again";
  } else if (error instanceof NetworkError) {
    if (error.statusCode === 503) {
      return "Service temporarily unavailable. Please try again later.";
    }
    return "Network error. Please check your connection.";
  } else if (error instanceof ValidationError) {
    return "Please check your input and try again.";
  }
  return "An error occurred. Please try again.";
}
```

### Implement Retry Logic

For network errors, implement retry logic:

```typescript
async function withRetry<T>(
  fn: () => Promise<T>,
  maxRetries = 3
): Promise<T> {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (error instanceof NetworkError && i < maxRetries - 1) {
        await new Promise((resolve) => setTimeout(resolve, 1000 * (i + 1)));
        continue;
      }
      throw error;
    }
  }
  throw new Error("Max retries exceeded");
}

// Usage
const vault = await withRetry(() =>
  sdk.vault.getVaultByKey("yusd", 1)
);
```

### Handle Token Expiration

Always handle token expiration gracefully:

```typescript
async function makeAuthenticatedRequest<T>(
  apiCall: (token: string) => Promise<T>
): Promise<T> {
  let accessToken = localStorage.getItem("accessToken");

  if (!accessToken || isTokenExpired(accessToken)) {
    accessToken = await refreshToken();
    if (!accessToken) {
      throw new AuthenticationError("Please login again");
    }
  }

  try {
    return await apiCall(accessToken);
  } catch (error) {
    if (error instanceof AuthenticationError) {
      // Token invalid, try refresh once
      accessToken = await refreshToken();
      if (accessToken) {
        return await apiCall(accessToken);
      }
    }
    throw error;
  }
}
```

### Log Errors Appropriately

Log errors for debugging but don't expose sensitive information:

```typescript
try {
  await sdk.auth.login(credentials);
} catch (error) {
  // Log full error for debugging (server-side or dev only)
  console.error("Login error:", error);

  // Show user-friendly message
  showError("Login failed. Please try again.");

  // Don't expose:
  // - Token values
  // - Internal error details
  // - Stack traces (to users)
}
```

### Handle Loading States

Show loading states during API calls:

```typescript
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);

async function fetchVaults() {
  setLoading(true);
  setError(null);

  try {
    const vaults = await sdk.vault.getVaults({ chainId: 1 });
    return vaults;
  } catch (err: any) {
    setError(err.message);
    throw err;
  } finally {
    setLoading(false);
  }
}
```

### Graceful Degradation

Handle partial failures gracefully:

```typescript
async function loadDashboard() {
  const results = await Promise.allSettled([
    sdk.vault.getProtocolStats(),
    sdk.vault.getVaults({ chainId: 1 }),
    sdk.vault.getStrategies(),
  ]);

  const stats = results[0].status === "fulfilled" ? results[0].value : null;
  const vaults = results[1].status === "fulfilled" ? results[1].value : null;
  const strategies = results[2].status === "fulfilled" ? results[2].value : null;

  // Show available data, indicate missing data
  return { stats, vaults, strategies };
}
```
