# Common Error Codes

Reference for Clore.ai API error codes and how to handle them.

## Response Code Structure

Every API response includes a `code` field:

```json
{
  "code": 0,
  "data": {...}
}
```

```json
{
  "code": 6,
  "error": "not_enough_balance"
}
```

## Error Codes

| Code | Meaning                 | HTTP Status |
| ---- | ----------------------- | ----------- |
| 0    | Success                 | 200         |
| 1    | Database error          | 500         |
| 2    | Invalid input           | 400         |
| 3    | Invalid/missing API key | 401         |
| 4    | Invalid endpoint        | 404         |
| 5    | Rate limit exceeded     | 429         |
| 6    | See error field         | varies      |

## Common Error Messages (Code 6)

### Order Creation Errors

| Error                         | Meaning                        | Solution                        |
| ----------------------------- | ------------------------------ | ------------------------------- |
| `server-dont-exist`           | Server ID not found            | Check marketplace for valid IDs |
| `server-offline`              | Server is offline              | Choose different server         |
| `server-already-rented`       | Server has active rental       | Wait or choose another          |
| `not_enough_balance`          | Insufficient funds             | Top up wallet                   |
| `cant_rent_from_yourself`     | Can't rent own server          | Use different account           |
| `too_low_price`               | Spot bid below minimum         | Increase bid price              |
| `you_already_have_spot_order` | Duplicate spot order           | Cancel existing first           |
| `currency-not-allowed`        | Server doesn't accept currency | Use different currency          |
| `machine-is-on-gigaspot`      | Server in gigaspot mode        | Use gigaspot API                |

### Order Management Errors

| Error                        | Meaning                 | Solution            |
| ---------------------------- | ----------------------- | ------------------- |
| `you_dont_own_this_order`    | Order not yours         | Check order ID      |
| `order_not_active`           | Order already ended     | No action needed    |
| `issue_description_too_long` | Issue text > 2048 chars | Shorten description |

### Spot Price Errors

| Error                         | Meaning                  | Solution              |
| ----------------------------- | ------------------------ | --------------------- |
| `order_dont_exist`            | Order not found          | Verify order ID       |
| `amount_too_low`              | Price below minimum      | Increase price        |
| `can_lower_every_600_seconds` | Rate limited             | Wait before lowering  |
| `exceeded_max_step`           | Price decrease too large | Use smaller decrement |

### Server Settings Errors

| Error                        | Meaning                     | Solution               |
| ---------------------------- | --------------------------- | ---------------------- |
| `server_dont_exist`          | Server not found            | Check server name      |
| `not_all_parameters_present` | Missing required fields     | Check documentation    |
| `invalid_mrl`                | Invalid max rental length   | Use valid range        |
| `invalid_input`              | Parameter validation failed | Check parameter values |

## Handling Errors in Python

```python
import requests
import time
from typing import Optional

class CloreAPIError(Exception):
    def __init__(self, code: int, message: str, response: dict):
        self.code = code
        self.message = message
        self.response = response
        super().__init__(f"[{code}] {message}")

class RateLimitError(CloreAPIError):
    pass

class InsufficientBalanceError(CloreAPIError):
    pass

class ServerNotAvailableError(CloreAPIError):
    pass

def handle_clore_response(response: dict) -> dict:
    """Handle Clore API response with proper error typing."""
    code = response.get("code", -1)
    
    if code == 0:
        return response
    
    error = response.get("error", "Unknown error")
    
    # Map error codes to exceptions
    if code == 5:
        raise RateLimitError(code, "Rate limit exceeded", response)
    
    if code == 3:
        raise CloreAPIError(code, "Invalid or missing API key", response)
    
    if code == 6:
        # Handle specific error messages
        if "not_enough_balance" in str(error):
            raise InsufficientBalanceError(code, error, response)
        
        if "server-already-rented" in str(error) or "server-offline" in str(error):
            raise ServerNotAvailableError(code, error, response)
    
    raise CloreAPIError(code, error, response)

def clore_request_with_retry(
    method: str, 
    url: str, 
    headers: dict,
    max_retries: int = 3,
    **kwargs
) -> dict:
    """Make Clore API request with retry logic."""
    
    for attempt in range(max_retries):
        try:
            response = requests.request(method, url, headers=headers, **kwargs)
            data = response.json()
            return handle_clore_response(data)
            
        except RateLimitError:
            # Exponential backoff
            wait_time = 2 ** attempt
            print(f"Rate limited, waiting {wait_time}s...")
            time.sleep(wait_time)
            
        except InsufficientBalanceError as e:
            # Don't retry - need user action
            raise e
            
        except ServerNotAvailableError as e:
            # Don't retry - need different server
            raise e
            
        except CloreAPIError as e:
            if attempt == max_retries - 1:
                raise e
            time.sleep(1)
    
    raise Exception("Max retries exceeded")

# Usage example
try:
    result = clore_request_with_retry(
        "POST", 
        "https://api.clore.ai/v1/create_order",
        headers={"auth": "YOUR_API_KEY"},
        json={...}
    )
except InsufficientBalanceError:
    print("Please top up your wallet")
except ServerNotAvailableError:
    print("Server not available, trying another...")
except RateLimitError:
    print("API rate limit - slow down requests")
except CloreAPIError as e:
    print(f"API error: {e}")
```

## Rate Limit Handling

The API allows **1 request per second**. Implement proper rate limiting:

```python
import time
from functools import wraps

class RateLimiter:
    def __init__(self, min_interval: float = 1.1):
        self.min_interval = min_interval
        self.last_request = 0
    
    def wait(self):
        elapsed = time.time() - self.last_request
        if elapsed < self.min_interval:
            time.sleep(self.min_interval - elapsed)
        self.last_request = time.time()

# Usage
rate_limiter = RateLimiter()

def make_request():
    rate_limiter.wait()
    # ... make request
```

## Debugging Tips

1. **Check the `error` field** - Code 6 always includes an `error` field with details
2. **Validate input** - Code 2 means your request data is malformed
3. **Check API key** - Code 3 means authentication failed
4. **Slow down** - Code 5 means you're hitting rate limits
5. **Check server status** - Some errors indicate server-side issues (try again later)

## See Also

* [API Quick Reference](/reference/api-reference.md)
* [Getting Started](/getting-started/quick-start.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dev.clore.ai/reference/error-codes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
