229 lines
5.9 KiB
Plaintext
229 lines
5.9 KiB
Plaintext
---
|
|
title: Error Handling
|
|
subtitle: Handle API errors, timeouts, and configure retries
|
|
slug: ts-sdk-reference/error-handling
|
|
---
|
|
|
|
The SDK raises typed exceptions for API errors. All errors extend `SkyvernError` and include the HTTP status code, response body, and raw response.
|
|
|
|
---
|
|
|
|
## Error types
|
|
|
|
| Exception | Status Code | When it's raised |
|
|
|-----------|-------------|------------------|
|
|
| `BadRequestError` | 400 | Invalid request parameters. |
|
|
| `ForbiddenError` | 403 | Invalid or missing API key. |
|
|
| `NotFoundError` | 404 | Resource (run, workflow, session) not found. |
|
|
| `ConflictError` | 409 | Resource conflict (e.g., duplicate creation). |
|
|
| `UnprocessableEntityError` | 422 | Request validation failed. |
|
|
| `SkyvernError` | Any | Base class for all API errors. Catch this as a fallback. |
|
|
| `SkyvernTimeoutError` | — | HTTP request timed out. |
|
|
|
|
Import errors from the package:
|
|
|
|
```typescript
|
|
import { SkyvernError, SkyvernTimeoutError, SkyvernApi } from "@skyvern/client";
|
|
|
|
// Base errors are top-level exports:
|
|
// SkyvernError — base class for all API errors
|
|
// SkyvernTimeoutError — HTTP request timed out
|
|
|
|
// HTTP status error subclasses are accessed via the SkyvernApi namespace:
|
|
// SkyvernApi.BadRequestError — 400
|
|
// SkyvernApi.ForbiddenError — 403
|
|
// SkyvernApi.NotFoundError — 404
|
|
// SkyvernApi.ConflictError — 409
|
|
// SkyvernApi.UnprocessableEntityError — 422
|
|
```
|
|
|
|
---
|
|
|
|
## Catching errors
|
|
|
|
```typescript
|
|
import { Skyvern, SkyvernError, SkyvernApi } from "@skyvern/client";
|
|
|
|
const skyvern = new Skyvern({ apiKey: "YOUR_API_KEY" });
|
|
|
|
try {
|
|
const run = await skyvern.getRun("tsk_nonexistent");
|
|
} catch (e) {
|
|
if (e instanceof SkyvernApi.NotFoundError) {
|
|
console.log(`Run not found: ${e.body}`);
|
|
} else if (e instanceof SkyvernError) {
|
|
console.log(`API error ${e.statusCode}: ${e.body}`);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Error properties
|
|
|
|
Every error has these attributes:
|
|
|
|
| Property | Type | Description |
|
|
|----------|------|-------------|
|
|
| `statusCode` | `number \| undefined` | HTTP status code. |
|
|
| `body` | `unknown` | Response body (usually an object with error details). |
|
|
| `rawResponse` | `RawResponse \| undefined` | The raw HTTP response. |
|
|
| `message` | `string` | Human-readable error message. |
|
|
|
|
---
|
|
|
|
## Timeouts
|
|
|
|
Two different timeouts apply:
|
|
|
|
### HTTP request timeout
|
|
|
|
Controls how long the SDK waits for the HTTP response from the Skyvern API. Set it in the constructor or per-request:
|
|
|
|
```typescript
|
|
// Global timeout (applies to all requests)
|
|
const skyvern = new Skyvern({
|
|
apiKey: "YOUR_API_KEY",
|
|
timeoutInSeconds: 30,
|
|
});
|
|
|
|
// Per-request timeout
|
|
const result = await skyvern.getRun("tsk_abc123", {
|
|
timeoutInSeconds: 10,
|
|
});
|
|
```
|
|
|
|
When an HTTP request times out, a `SkyvernTimeoutError` is thrown.
|
|
|
|
### Completion timeout
|
|
|
|
Controls how long `waitForCompletion` polls before giving up. This is separate from the HTTP timeout:
|
|
|
|
```typescript
|
|
try {
|
|
const result = await skyvern.runTask({
|
|
body: {
|
|
prompt: "Extract data",
|
|
url: "https://example.com",
|
|
},
|
|
waitForCompletion: true,
|
|
timeout: 300, // Give up after 5 minutes
|
|
});
|
|
} catch (e) {
|
|
if (e instanceof Error && e.message.includes("Timeout")) {
|
|
console.log("Task didn't complete in time");
|
|
}
|
|
}
|
|
```
|
|
|
|
The completion timeout throws a standard JavaScript `Error` with a timeout message.
|
|
|
|
---
|
|
|
|
## Retries
|
|
|
|
Configure automatic retries for transient failures. Set it in the constructor or per-request:
|
|
|
|
```typescript
|
|
// Global retries (default: 2)
|
|
const skyvern = new Skyvern({
|
|
apiKey: "YOUR_API_KEY",
|
|
maxRetries: 3,
|
|
});
|
|
|
|
// Per-request retries
|
|
const result = await skyvern.runTask(
|
|
{
|
|
body: {
|
|
prompt: "Extract product data",
|
|
url: "https://example.com/products",
|
|
},
|
|
},
|
|
{ maxRetries: 5 },
|
|
);
|
|
```
|
|
|
|
Retries apply to the HTTP request level (network errors, 5xx responses). They do not retry the entire task if it fails at the AI level — use `getRun` to check the status and re-run if needed.
|
|
|
|
---
|
|
|
|
## Abort requests
|
|
|
|
Cancel in-flight requests using `AbortSignal`:
|
|
|
|
```typescript
|
|
const controller = new AbortController();
|
|
|
|
// Cancel after 10 seconds
|
|
setTimeout(() => controller.abort(), 10000);
|
|
|
|
try {
|
|
const result = await skyvern.runTask(
|
|
{
|
|
body: {
|
|
prompt: "Extract data",
|
|
url: "https://example.com",
|
|
},
|
|
},
|
|
{ abortSignal: controller.signal },
|
|
);
|
|
} catch (e) {
|
|
if (e instanceof Error && e.name === "AbortError") {
|
|
console.log("Request was aborted");
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Run failure vs API errors
|
|
|
|
There are two distinct failure modes:
|
|
|
|
**API error** — The HTTP request itself failed. The SDK throws an exception.
|
|
|
|
```typescript
|
|
import { SkyvernError } from "@skyvern/client";
|
|
|
|
try {
|
|
const result = await skyvern.runTask({
|
|
body: { prompt: "..." },
|
|
});
|
|
} catch (e) {
|
|
if (e instanceof SkyvernError) {
|
|
console.log(`API call failed: ${e.statusCode}`);
|
|
}
|
|
}
|
|
```
|
|
|
|
**Run failure** — The API call succeeded, but the task/workflow failed during execution. No exception is thrown. Check the `status` field:
|
|
|
|
```typescript
|
|
const result = await skyvern.runTask({
|
|
body: {
|
|
prompt: "Fill out the form",
|
|
url: "https://example.com",
|
|
},
|
|
waitForCompletion: true,
|
|
});
|
|
|
|
if (result.status === "failed") {
|
|
console.log(`Task failed: ${result.failure_reason}`);
|
|
} else if (result.status === "timed_out") {
|
|
console.log(`Task exceeded step limit after ${result.step_count} steps`);
|
|
} else if (result.status === "completed") {
|
|
console.log(`Success: ${JSON.stringify(result.output)}`);
|
|
}
|
|
```
|
|
|
|
### Run statuses
|
|
|
|
| Status | Description |
|
|
|--------|-------------|
|
|
| `created` | Run initialized, not yet queued. |
|
|
| `queued` | Waiting for an available browser. |
|
|
| `running` | AI is executing. |
|
|
| `completed` | Finished successfully. |
|
|
| `failed` | Encountered an error during execution. |
|
|
| `terminated` | Manually stopped. |
|
|
| `timed_out` | Exceeded step limit (`max_steps`). |
|
|
| `canceled` | Canceled before starting. |
|