Skip to main content
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

ExceptionStatus CodeWhen it’s raised
BadRequestError400Invalid request parameters.
ForbiddenError403Invalid or missing API key.
NotFoundError404Resource (run, workflow, session) not found.
ConflictError409Resource conflict (e.g., duplicate creation).
UnprocessableEntityError422Request validation failed.
SkyvernErrorAnyBase class for all API errors. Catch this as a fallback.
SkyvernTimeoutErrorHTTP request timed out.
Import errors from the package:
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

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:
PropertyTypeDescription
statusCodenumber | undefinedHTTP status code.
bodyunknownResponse body (usually an object with error details).
rawResponseRawResponse | undefinedThe raw HTTP response.
messagestringHuman-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:
// 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:
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:
// 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:
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.
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:
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

StatusDescription
createdRun initialized, not yet queued.
queuedWaiting for an available browser.
runningAI is executing.
completedFinished successfully.
failedEncountered an error during execution.
terminatedManually stopped.
timed_outExceeded step limit (max_steps).
canceledCanceled before starting.