> ## 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.';
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.