# Error Handling

The Bizora API uses standard HTTP status codes and returns errors in a simple JSON format.

## Common Errors

### 401 - Invalid API Key

Your API key is missing or incorrect:

```python
try:
    stream = client.chat.completions.create(
        model="bizora-1.0",
        messages=[{"role": "human", "content": "What is section 179?"}],
        stream=True
    )
    for chunk in stream:
        if chunk.choices and chunk.choices[0].delta.content:
            print(chunk.choices[0].delta.content, end="", flush=True)
except openai.AuthenticationError as e:
    print(f"❌ Authentication error: {e.message}")
    print("Please check your API key")
```

```javascript
try {
  const stream = await client.chat.completions.create({
    model: 'bizora-1.0',
    messages: [{ role: 'human', content: 'What is section 179?' }],
    stream: true
  });
  
  for await (const chunk of stream) {
    if (chunk.choices[0]?.delta?.content) {
      process.stdout.write(chunk.choices[0].delta.content);
    }
  }
} catch (error) {
  if (error.status === 401) {
    console.log('❌ Authentication error');
    console.log('Please check your API key');
  }
}
```

### 402 - Insufficient Balance

Add credits to your account to continue.

```json
{
  "error": {
    "type": "insufficient_balance",
    "message": "Please add credits to your account"
  }
}
```

### 429 - Rate Limit

You're making requests too quickly. Implement retry logic with exponential backoff:

```python
import time
import openai

def make_request_with_retry(max_retries=3):
    for attempt in range(max_retries):
        try:
            stream = client.chat.completions.create(
                model="bizora-1.0",
                messages=[{"role": "human", "content": "What is section 179?"}],
                stream=True
            )
            for chunk in stream:
                if chunk.choices and chunk.choices[0].delta.content:
                    print(chunk.choices[0].delta.content, end="", flush=True)
            return
        except openai.RateLimitError:
            wait_time = 2 ** attempt  # Exponential backoff
            print(f"Rate limited. Waiting {wait_time}s...")
            time.sleep(wait_time)
    print("Max retries reached")

make_request_with_retry()
```

```javascript
async function makeRequestWithRetry(maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const stream = await client.chat.completions.create({
        model: 'bizora-1.0',
        messages: [{ role: 'human', content: 'What is section 179?' }],
        stream: true
      });
      
      for await (const chunk of stream) {
        if (chunk.choices[0]?.delta?.content) {
          process.stdout.write(chunk.choices[0].delta.content);
        }
      }
      return;
    } catch (error) {
      if (error.status === 429) {
        const waitTime = Math.pow(2, attempt) * 1000; // Exponential backoff
        console.log(`Rate limited. Waiting ${waitTime/1000}s...`);
        await new Promise(resolve => setTimeout(resolve, waitTime));
      } else {
        throw error;
      }
    }
  }
  console.log('Max retries reached');
}

await makeRequestWithRetry();
```

## Handling Errors in Streaming

Wrap streaming code in try-catch to handle errors properly:

```python
try:
    stream = client.chat.completions.create(
        model="bizora-1.0",
        messages=[{"role": "human", "content": "What is section 179?"}],
        stream=True
    )
    
    for chunk in stream:
        if chunk.choices and chunk.choices[0].delta.content:
            print(chunk.choices[0].delta.content, end="", flush=True)
            
except openai.APIError as e:
    print(f"\n❌ API error: {e.message}")
except openai.AuthenticationError as e:
    print(f"\n❌ Authentication error: {e.message}")
except openai.RateLimitError as e:
    print(f"\n❌ Rate limit error: {e.message}")
except Exception as e:
    print(f"\n❌ Unexpected error: {str(e)}")
```

```javascript
try {
  const stream = await client.chat.completions.create({
    model: 'bizora-1.0',
    messages: [{ role: 'human', content: 'What is section 179?' }],
    stream: true
  });
  
  for await (const chunk of stream) {
    if (chunk.choices[0]?.delta?.content) {
      process.stdout.write(chunk.choices[0].delta.content);
    }
  }
} catch (error) {
  if (error.status === 401) {
    console.log('\n❌ Authentication error');
  } else if (error.status === 429) {
    console.log('\n❌ Rate limit error');
  } else if (error.status === 402) {
    console.log('\n❌ Insufficient balance');
  } else {
    console.log(`\n❌ Error: ${error.message}`);
  }
}
```

## Best Practices

- **Wrap API calls in try-catch** - Always handle potential errors
- **Check your balance** - Monitor your account balance in the dashboard
- **Add retry logic** - Retry failed requests with exponential backoff
- **Log errors** - Keep track of errors for debugging

That's it! The OpenAI SDK handles most error cases automatically.
