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

# Error Handling

## GraphyApiError

All API errors are wrapped in `GraphyApiError`. Each error carries structured metadata you can use to decide how to handle the failure:

```typescript theme={null}
import { isGraphyApiError } from '@graphysdk/agents-sdk';

try {
  const result = await ai.generateGraph({ config, userPrompt });
} catch (error) {
  if (isGraphyApiError(error)) {
    console.error(`[${error.code}] ${error.message} (HTTP ${error.status})`);
    if (error.retryable) {
      // schedule retry
    }
  }
}
```

| Property    | Type                  | Description                                    |
| ----------- | --------------------- | ---------------------------------------------- |
| `message`   | `string`              | Human-readable error description               |
| `status`    | `number \| undefined` | HTTP status code, if from an HTTP response     |
| `code`      | `string \| undefined` | Machine-readable error code from the API       |
| `retryable` | `boolean`             | Whether the SDK considers this error retryable |

Use the `isGraphyApiError()` type guard to safely narrow unknown errors. See the [Type Reference](/agents/reference/types#graphyapierror) for the full class definition.

***

## Retry Behavior

The SDK automatically retries failed requests based on `retryConfig`.

**Default configuration:**

```typescript theme={null}
{
  attempts: 3,
  delay: 1000,
  backoff: 2
}
```

**Retry delay formula:**

```
delay * (backoff ^ (attempt - 1))
```

With defaults:

| Attempt | Delay     |
| ------- | --------- |
| 1       | Immediate |
| 2       | 1000ms    |
| 3       | 2000ms    |

### Retryable Conditions

| Condition             | Retries |
| --------------------- | ------- |
| HTTP 5xx              | Yes     |
| HTTP 429 (rate limit) | Yes     |
| Network failure       | Yes     |
| HTTP 4xx (except 429) | No      |
| User abort            | No      |
| `GraphyApiError`      | No      |

### Custom Retry Configuration

```typescript theme={null}
const ai = new GraphyAiSdk({
  apiKey: process.env.GRAPHY_API_KEY,
  baseUrl: 'https://agents.graphy.dev',
  retryConfig: {
    attempts: 5, // More attempts
    delay: 500, // Shorter initial delay
    backoff: 1.5, // Gentler backoff
  },
});
```

### Disable Retries

```typescript theme={null}
const ai = new GraphyAiSdk({
  apiKey: process.env.GRAPHY_API_KEY,
  baseUrl: 'https://agents.graphy.dev',
  retryConfig: {
    attempts: 1, // No retries
    delay: 0,
    backoff: 1,
  },
});
```

***

## Error Codes

Errors from the API include a `code` field:

| Code                   | HTTP Status | Retryable | Description                        |
| ---------------------- | ----------- | --------- | ---------------------------------- |
| `VALIDATION_ERROR`     | 400         | No        | Invalid request body or parameters |
| `AUTHENTICATION_ERROR` | 401         | No        | Invalid or missing API key         |
| `RATE_LIMIT_ERROR`     | 429         | Yes       | Too many requests                  |
| `PROCESSING_ERROR`     | 500         | Yes       | Internal processing failure        |
| `TIMEOUT_ERROR`        | 504         | Yes       | Request took too long              |

***

## Network Errors

Network failures throw a `GraphyApiError` with `retryable: true`:

```typescript theme={null}
try {
  const result = await ai.generateGraph({ config, userPrompt });
} catch (error) {
  if (isGraphyApiError(error) && error.retryable) {
    console.error('Transient error, consider retrying');
  }
}
```

***

## Abort Errors

User cancellation throws a native `AbortError`:

```typescript theme={null}
const controller = new AbortController();

try {
  const result = await ai.generateGraph({ config, userPrompt }, undefined, controller.signal);
} catch (error) {
  if (error instanceof Error && error.name === 'AbortError') {
    // User cancelled - not an error
    return;
  }
  throw error;
}
```

***

## Stream Errors

In streaming mode, errors can arrive as events:

```typescript theme={null}
import { isErrorEvent } from '@graphysdk/agents-sdk';

for await (const event of stream) {
  if (isErrorEvent(event)) {
    console.error('Error:', event.error);
    console.error('Code:', event.code);
    console.error('Retryable:', event.retryable);

    if (event.retryable) {
      // Implement retry logic
    }
    return;
  }
}
```

Or as exceptions when the stream fails:

```typescript theme={null}
import { isGraphyApiError } from '@graphysdk/agents-sdk';

try {
  for await (const event of stream) {
    // ...
  }
} catch (error) {
  if (error instanceof Error && error.name === 'AbortError') {
    return; // User cancelled
  }
  if (isGraphyApiError(error)) {
    console.error('API error:', error.message);
  }
}
```

***

## Timeout Errors

The SDK throws `AbortError` when a request exceeds the configured timeout:

```typescript theme={null}
const ai = new GraphyAiSdk({
  apiKey: process.env.GRAPHY_API_KEY,
  baseUrl: 'https://agents.graphy.dev',
  timeout: 10000, // 10 seconds
});

try {
  const result = await ai.generateGraph({ config, userPrompt });
} catch (error) {
  if (error instanceof Error && error.name === 'AbortError') {
    console.error('Request timed out');
  }
}
```

***

## Best Practices

### Log errors with context

```typescript theme={null}
try {
  const result = await ai.generateGraph({ config, userPrompt });
} catch (error) {
  if (error instanceof Error) {
    logger.error('generateGraph failed', {
      error: error.message,
      userPrompt,
      configType: config.type,
    });
  }
  throw error;
}
```

### Show user-friendly messages

```typescript theme={null}
function getErrorMessage(error: unknown): string {
  if (isGraphyApiError(error)) {
    if (error.status === 401) return 'Authentication failed. Please check your API key.';
    if (error.status === 429) return 'Too many requests. Please try again later.';
    if (error.retryable) return 'Temporary issue. Please try again.';
    return 'Failed to generate chart. Please try again.';
  }
  if (error instanceof Error && error.name === 'AbortError') {
    return 'Request was cancelled.';
  }
  return 'An unexpected error occurred.';
}
```
