> ## Documentation Index
> Fetch the complete documentation index at: https://docs.leokit.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Debugging

> Debug failed transactions using trace IDs and error tracking

LeoKit provides comprehensive error tracking through trace IDs. Every API error includes a `trace_id` that you can use to retrieve detailed debugging information, including the full request context, error details, and timestamps.

## How Trace IDs Work

When an API request fails, the error response includes a `trace_id`:

```json theme={null}
{
  "error": "Insufficient balance (including gas fees).",
  "status": 400,
  "code": "INSUFFICIENT_BALANCE",
  "trace_id": "tr_abc123xyz456",
  "context": {
    "required": "1.05 ETH",
    "available": "1.00 ETH"
  }
}
```

You can use this `trace_id` to retrieve full error details from the tracking endpoint.

## Retrieving Error Details

### Endpoint

```
GET /leokit/trace/[traceId]
```

### Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET 'https://api.leodex.io/leokit/trace/tr_abc123xyz456' \
    -H 'Api-Key: your_api_key_here'
  ```

  ```javascript JavaScript theme={null}
  const trace = await fetch(
    "https://api.leodex.io/leokit/trace/tr_abc123xyz456",
    {
      headers: {
        "Api-Key": "your_api_key_here"
      }
    }
  ).then(r => r.json());

  console.log("Error occurred at:", trace.timestamp);
  console.log("Endpoint:", trace.endpoint);
  console.log("Error details:", trace.error_details);
  ```
</CodeGroup>

### Response

```json theme={null}
{
  "trace_id": "tr_abc123xyz456",
  "client_api": "client_key_here",
  "error_details": {
    "code": "INSUFFICIENT_BALANCE",
    "message": "Insufficient balance (including gas fees).",
    "status": 400,
    "context": {
      "required": "1.05 ETH",
      "available": "1.00 ETH",
      "gas_estimate": "0.05 ETH"
    }
  },
  "timestamp": "2026-01-15T12:34:56.789Z",
  "endpoint": "/leokit/deposit",
  "request_params": {
    "quote_id": "01936b4a-7c8e-7890-abcd-ef1234567890",
    "selected_protocol": "thorchain"
  }
}
```

## Response Fields

| Field                   | Description                               |
| ----------------------- | ----------------------------------------- |
| `trace_id`              | Unique identifier for this error          |
| `client_api`            | Your API key (for verification)           |
| `error_details.code`    | Error code (e.g., `INSUFFICIENT_BALANCE`) |
| `error_details.message` | Human-readable error message              |
| `error_details.status`  | HTTP status code                          |
| `error_details.context` | Additional context (varies by error)      |
| `timestamp`             | When the error occurred (ISO 8601)        |
| `endpoint`              | Which API endpoint failed                 |
| `request_params`        | Parameters that were sent                 |

## Common Use Cases

### 1. Debugging Failed Deposits

```javascript theme={null}
async function debugFailedDeposit(traceId) {
  const trace = await fetch(
    `https://api.leodex.io/leokit/trace/${traceId}`,
    { headers: { "Api-Key": "your_api_key_here" } }
  ).then(r => r.json());

  console.log("Failed endpoint:", trace.endpoint);
  console.log("Quote ID:", trace.request_params.quote_id);
  console.log("Protocol:", trace.request_params.selected_protocol);
  console.log("Error:", trace.error_details.message);

  // Check specific error types
  if (trace.error_details.code === "INSUFFICIENT_BALANCE") {
    console.log("User needs:", trace.error_details.context.required);
    console.log("User has:", trace.error_details.context.available);
  }
}
```

### 2. Error Pattern Analysis

Track error frequencies to identify systemic issues:

```javascript theme={null}
async function analyzeErrorPatterns(traceIds) {
  const traces = await Promise.all(
    traceIds.map(id =>
      fetch(`https://api.leodex.io/leokit/trace/${id}`, {
        headers: { "Api-Key": "your_api_key_here" }
      }).then(r => r.json())
    )
  );

  // Group by error code
  const errorCounts = traces.reduce((acc, trace) => {
    const code = trace.error_details.code;
    acc[code] = (acc[code] || 0) + 1;
    return acc;
  }, {});

  console.log("Error distribution:", errorCounts);
  // Output: { INSUFFICIENT_BALANCE: 5, QUOTE_EXPIRED: 2, ... }
}
```

### 3. Customer Support Integration

Display error details to support agents:

```javascript theme={null}
function SupportTicket({ traceId }) {
  const [trace, setTrace] = useState(null);

  useEffect(() => {
    fetch(`https://api.leodex.io/leokit/trace/${traceId}`, {
      headers: { "Api-Key": "your_api_key_here" }
    })
      .then(r => r.json())
      .then(setTrace);
  }, [traceId]);

  if (!trace) return <p>Loading error details...</p>;

  return (
    <div className="support-ticket">
      <h2>Error Report</h2>
      <dl>
        <dt>Time:</dt>
        <dd>{new Date(trace.timestamp).toLocaleString()}</dd>

        <dt>Error Code:</dt>
        <dd>{trace.error_details.code}</dd>

        <dt>Message:</dt>
        <dd>{trace.error_details.message}</dd>

        <dt>Endpoint:</dt>
        <dd>{trace.endpoint}</dd>

        <dt>Request Parameters:</dt>
        <dd><pre>{JSON.stringify(trace.request_params, null, 2)}</pre></dd>
      </dl>
    </div>
  );
}
```

### 4. Automated Monitoring

Set up alerts for critical errors:

```javascript theme={null}
async function monitorErrors(traceIds) {
  const criticalErrors = [
    'INTERNAL_SERVER_ERROR',
    'PROTOCOL_TIMEOUT',
    'BLOCKCHAIN_SYNC_ERROR'
  ];

  for (const traceId of traceIds) {
    const trace = await fetch(
      `https://api.leodex.io/leokit/trace/${traceId}`,
      { headers: { "Api-Key": "your_api_key_here" } }
    ).then(r => r.json());

    if (criticalErrors.includes(trace.error_details.code)) {
      // Send alert to monitoring system
      await sendAlert({
        severity: 'critical',
        message: trace.error_details.message,
        traceId: trace.trace_id,
        timestamp: trace.timestamp
      });
    }
  }
}
```

## Error Categories

Errors are grouped into categories for easier debugging:

### Validation Errors (HTTP 400)

Client-side issues like invalid parameters or malformed requests.

**Common Codes:**

* `BAD_REQUEST` - Malformed JSON or invalid types
* `WRONG_PROTOCOL` - Unsupported protocol selected
* `INVALID_TOLERANCE_BPS` - Slippage tolerance out of range

**Debugging:**

```javascript theme={null}
if (trace.error_details.status === 400) {
  console.log("Fix client-side validation:");
  console.log("- Check parameter types");
  console.log("- Verify required fields");
  console.log("- Validate addresses");
}
```

### Balance & Amount Errors (HTTP 400)

Insufficient funds or amounts outside valid ranges.

**Common Codes:**

* `INSUFFICIENT_BALANCE` - Not enough tokens/gas
* `NOT_ENOUGH_GAS` - Can't pay transaction fees
* `UNDER_DUST_LIMIT` - Output amount too small

**Debugging:**

```javascript theme={null}
if (trace.error_details.code === 'INSUFFICIENT_BALANCE') {
  const { required, available } = trace.error_details.context;
  console.log(`User needs ${required} but has ${available}`);
  console.log("Suggest: Reduce swap amount or add funds");
}
```

### Quote & Transaction Errors (HTTP 400/404)

Issues with quotes or transaction generation.

**Common Codes:**

* `QUOTE_EXPIRED` - Quote older than 15 minutes
* `QUOTE_NOT_FOUND` - Invalid quote\_id
* `NO_ROUTES_AVAILABLE` - No protocols support this swap

**Debugging:**

```javascript theme={null}
if (trace.error_details.code === 'QUOTE_EXPIRED') {
  console.log("Quote expired at:", trace.timestamp);
  console.log("Suggest: Request a new quote");
}
```

### Server & Protocol Errors (HTTP 500/503)

Backend or protocol integration issues.

**Common Codes:**

* `INTERNAL_SERVER_ERROR` - Unexpected server error
* `PROTOCOL_TIMEOUT` - Protocol didn't respond in time
* `BLOCKCHAIN_SYNC_ERROR` - Node syncing issue

**Debugging:**

```javascript theme={null}
if (trace.error_details.status >= 500) {
  console.log("Server-side issue - retry may help");
  console.log("If persists, contact support with trace_id:", trace.trace_id);
}
```

## Retention Policy

<Info>
  Error logs are retained for **30 days**. Download critical traces within this window.
</Info>

After 30 days, the trace endpoint will return:

```json theme={null}
{
  "error": "Trace not found or expired",
  "status": 404,
  "code": "TRACE_NOT_FOUND"
}
```

## Best Practices

<Check>
  **Always save trace\_id** - Store it in your database alongside transaction records for later debugging.
</Check>

<Check>
  **Show trace\_id to users** - Include it in error messages so users can reference it in support tickets.
</Check>

<Check>
  **Implement retry logic** - For transient errors like `PROTOCOL_TIMEOUT`, automatically retry with exponential backoff.
</Check>

<Check>
  **Log error patterns** - Track which errors occur most frequently to improve your integration.
</Check>

<Check>
  **Use context fields** - The `context` object contains actionable debugging information specific to each error type.
</Check>

## Error Response Handling

Build a robust error handler that uses trace IDs:

```javascript theme={null}
async function handleApiError(error) {
  if (!error.trace_id) {
    console.error("No trace_id available");
    return;
  }

  // Fetch full error details
  const trace = await fetch(
    `https://api.leodex.io/leokit/trace/${error.trace_id}`,
    { headers: { "Api-Key": "your_api_key_here" } }
  ).then(r => r.json());

  // Log to monitoring service
  await logToMonitoring({
    traceId: trace.trace_id,
    errorCode: trace.error_details.code,
    endpoint: trace.endpoint,
    timestamp: trace.timestamp
  });

  // Show user-friendly message
  const userMessage = getUserFriendlyMessage(trace.error_details.code);
  showNotification({
    type: 'error',
    message: userMessage,
    traceId: trace.trace_id
  });

  // Decide if we should retry
  if (isRetryableError(trace.error_details.code)) {
    await retryWithBackoff(trace.endpoint, trace.request_params);
  }
}

function isRetryableError(code) {
  return [
    'PROTOCOL_TIMEOUT',
    'INTERNAL_SERVER_ERROR',
    'SERVICE_UNAVAILABLE'
  ].includes(code);
}
```

## Next Steps

<CardGroup cols="2">
  <Card title="Error Reference" icon="book" href="/api-reference/errors">
    Complete list of all 46 error codes
  </Card>

  <Card title="Complete Swap Flow" icon="arrow-right-arrow-left" href="/guides/complete-swap-flow">
    Learn the complete swap workflow
  </Card>
</CardGroup>
