> ## Documentation Index
> Fetch the complete documentation index at: https://tokenlayer-2a53bba4.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Handling

> Understanding and handling API errors

## Error Response Format

All Thrust API errors follow a consistent format:

```json theme={null}
{
  "success": false,
  "error": "Descriptive error message"
}
```

## HTTP Status Codes

The API uses standard HTTP status codes to indicate success or failure:

| Status Code | Meaning               | Description                                   |
| ----------- | --------------------- | --------------------------------------------- |
| 200         | OK                    | Request successful                            |
| 400         | Bad Request           | Invalid parameters or missing required fields |
| 401         | Unauthorized          | Authentication required or token invalid      |
| 403         | Forbidden             | Insufficient permissions                      |
| 404         | Not Found             | Resource doesn't exist                        |
| 405         | Method Not Allowed    | Wrong HTTP method (all endpoints use POST)    |
| 500         | Internal Server Error | Server-side error                             |

## Common Error Messages

### Authentication Errors

#### Missing Authorization Header

```json theme={null}
{
  "error": "Missing authorization header"
}
```

**Solution**: Include the `Authorization: Bearer {token}` header in your request.

<CodeGroup>
  ```javascript JavaScript theme={null}
  const response = await fetch(endpoint, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`, // ✅ Don't forget this!
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(data)
  });
  ```

  ```bash cURL theme={null}
  curl -X POST "${ENDPOINT}" \
    -H "Authorization: Bearer ${JWT_TOKEN}" \  # ✅ Include auth header
    -H "Content-Type: application/json" \
    -d '{"data": "value"}'
  ```
</CodeGroup>

#### Invalid or Expired Token

```json theme={null}
{
  "error": "Invalid or expired authentication token"
}
```

**Solution**: Refresh your JWT token or re-authenticate.

```javascript theme={null}
const handleExpiredToken = async () => {
  try {
    // Try the API call
    const response = await apiCall();
    return response;
  } catch (error) {
    if (error.message.includes('expired')) {
      // Refresh token and retry
      await refreshAuthToken();
      return await apiCall();
    }
    throw error;
  }
};
```

#### No User ID in Token

```json theme={null}
{
  "error": "No user ID in token"
}
```

**Solution**: The JWT token is malformed. Obtain a new token from Ory.

### Validation Errors

#### Missing Required Fields

```json theme={null}
{
  "error": "Missing required fields: tokenId, chainSlug"
}
```

**Solution**: Include all required fields in your request body.

```javascript theme={null}
// ❌ Bad
{
  "chainSlug": "base"
}

// ✅ Good
{
  "tokenId": "550e8400-e29b-41d4-a716-446655440000",
  "chainSlug": "base"
}
```

#### Invalid Parameters

```json theme={null}
{
  "error": "Invalid filter value. Must be one of: trending, new, popular, top_posts"
}
```

**Solution**: Use only allowed values for enum fields.

### Resource Errors

#### Token Not Found

```json theme={null}
{
  "error": "Token not found"
}
```

**Solution**: Verify the `tokenId` exists and is correct.

```javascript theme={null}
// Check if token exists before making requests
const checkToken = async (tokenId) => {
  const response = await fetch(`${API_URL}/tag-coin`, {
    method: 'POST',
    headers: { /* ... */ },
    body: JSON.stringify({ slug: tokenId })
  });

  if (!response.ok) {
    throw new Error('Token not found');
  }

  return response.json();
};
```

#### Token Not Available on Chain

```json theme={null}
{
  "error": "Token not available on chain base-sepolia"
}
```

**Solution**: Use a supported chain for the token. Check `token_addresses` to see available chains.

### Trading Errors

#### Insufficient Liquidity

```json theme={null}
{
  "error": "UniswapV3 quote failed for all fee tiers. Pool may not exist or have insufficient liquidity"
}
```

**Solution**: The token may have graduated but not have sufficient Uniswap V3 liquidity yet. Try a smaller amount or wait for more liquidity.

#### Insufficient Balance

```json theme={null}
{
  "error": "Insufficient token balance"
}
```

**Solution**: User doesn't have enough tokens to complete the transaction.

```javascript theme={null}
// Check balance before attempting trade
const balance = await getUserBalance(userId, tokenId);
if (balance < amount) {
  throw new Error('Insufficient balance');
}
```

### Permission Errors

#### Access Denied to Club

```json theme={null}
{
  "error": "Access denied: You don't have permission to view this club"
}
```

**Solution**: User needs to hold the required token or meet visibility rules to access the club.

### Method Errors

#### Wrong HTTP Method

```json theme={null}
{
  "error": "Method not allowed"
}
```

**Solution**: All Thrust API endpoints use **POST** requests, not GET.

```javascript theme={null}
// ❌ Bad
fetch(endpoint, { method: 'GET' })

// ✅ Good
fetch(endpoint, { method: 'POST', body: JSON.stringify(data) })
```

## Error Handling Best Practices

### 1. Always Check Response Status

```javascript theme={null}
const apiCall = async (endpoint, data) => {
  const response = await fetch(endpoint, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(data)
  });

  const result = await response.json();

  if (!response.ok) {
    throw new Error(result.error || `HTTP ${response.status}`);
  }

  return result;
};
```

### 2. Implement Retry Logic

```javascript theme={null}
const apiCallWithRetry = async (endpoint, data, maxRetries = 3) => {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await apiCall(endpoint, data);
    } catch (error) {
      if (i === maxRetries - 1) throw error;

      // Exponential backoff
      await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
    }
  }
};
```

### 3. Handle Specific Error Types

```javascript theme={null}
const handleApiError = (error) => {
  if (error.message.includes('expired')) {
    // Refresh token
    return refreshAndRetry();
  } else if (error.message.includes('not found')) {
    // Show 404 UI
    showNotFoundMessage();
  } else if (error.message.includes('Insufficient')) {
    // Show balance error
    showInsufficientBalanceError();
  } else {
    // Generic error handling
    showGenericError(error.message);
  }
};
```

### 4. Use Try-Catch Blocks

```javascript theme={null}
const safeFetchTokens = async () => {
  try {
    const tokens = await fetchTokens();
    return { success: true, data: tokens };
  } catch (error) {
    console.error('Failed to fetch tokens:', error);
    return { success: false, error: error.message };
  }
};
```

### 5. Validate Before API Calls

```javascript theme={null}
const createPost = async (postData) => {
  // Client-side validation
  if (!postData.title || !postData.content) {
    throw new Error('Title and content are required');
  }

  if (postData.title.length > 200) {
    throw new Error('Title too long (max 200 characters)');
  }

  // Make API call
  return await apiCall('/create-post', postData);
};
```

## Debugging Tips

### Enable Detailed Logging

```javascript theme={null}
const DEBUG = true;

const apiCall = async (endpoint, data) => {
  if (DEBUG) {
    console.log('API Request:', { endpoint, data });
  }

  try {
    const response = await fetch(endpoint, {
      method: 'POST',
      headers: { /* ... */ },
      body: JSON.stringify(data)
    });

    const result = await response.json();

    if (DEBUG) {
      console.log('API Response:', { status: response.status, result });
    }

    return result;
  } catch (error) {
    if (DEBUG) {
      console.error('API Error:', error);
    }
    throw error;
  }
};
```

### Check Request Headers

```javascript theme={null}
// Verify your auth token is correctly formatted
const token = localStorage.getItem('jwt_token');
console.log('Token:', token.substring(0, 20) + '...');

// Check if token is expired
const parseJwt = (token) => {
  const base64Url = token.split('.')[1];
  const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
  const jsonPayload = decodeURIComponent(
    atob(base64).split('').map(c => {
      return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join('')
  );

  return JSON.parse(jsonPayload);
};

const payload = parseJwt(token);
console.log('Token expires:', new Date(payload.exp * 1000));
```

### Test with cURL

When debugging, use cURL to isolate issues:

```bash theme={null}
curl -v -X POST "https://yppncslmsswqydhhgygz.supabase.co/functions/v1/get-tokens" \
  -H "Authorization: Bearer ${JWT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "filter": "trending",
    "limit": 1
  }'
```

The `-v` flag shows verbose output including headers and response codes.

## Rate Limiting

While not explicitly documented, consider implementing rate limiting on your end:

```javascript theme={null}
class RateLimiter {
  constructor(maxRequests = 100, windowMs = 60000) {
    this.maxRequests = maxRequests;
    this.windowMs = windowMs;
    this.requests = [];
  }

  async checkLimit() {
    const now = Date.now();
    this.requests = this.requests.filter(time => now - time < this.windowMs);

    if (this.requests.length >= this.maxRequests) {
      throw new Error('Rate limit exceeded');
    }

    this.requests.push(now);
  }
}

const limiter = new RateLimiter();

const apiCall = async (endpoint, data) => {
  await limiter.checkLimit();
  // Make API call...
};
```

## Getting Help

If you encounter errors not covered here:

1. Check the [API Reference](/api-reference) for endpoint-specific documentation
2. Search or ask in our [Discord community](https://discord.gg/thrust)
3. Email [support@thrust.app](mailto:support@thrust.app) with:
   * The endpoint you're calling
   * Your request payload (remove sensitive data)
   * The error response
   * Your API client/SDK version

<Card title="API Reference" icon="book" href="/api-reference">
  View detailed documentation for all endpoints
</Card>
