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

# Error Codes

> Complete reference for BAP error codes, recovery hints, and retry behavior.

All BAP errors follow JSON-RPC 2.0 error format with extended `data` providing recovery guidance for agents.

## Error Response Format

```json theme={null}
{
  "code": -32012,
  "message": "Element not found",
  "data": {
    "retryable": true,
    "retryAfterMs": 500,
    "details": { "selector": { "type": "text", "value": "Submit" } },
    "recoveryHint": "Run observe() to refresh interactive elements, then retry with an updated selector"
  }
}
```

<ResponseField name="code" type="number" required>
  Numeric error code from the table below.
</ResponseField>

<ResponseField name="message" type="string" required>
  Human-readable error message.
</ResponseField>

<ResponseField name="data.retryable" type="boolean">
  Whether the operation can be retried.
</ResponseField>

<ResponseField name="data.retryAfterMs" type="number">
  Suggested delay before retrying (milliseconds).
</ResponseField>

<ResponseField name="data.details" type="object">
  Additional context (selector used, page ID, etc.).
</ResponseField>

<ResponseField name="data.recoveryHint" type="string">
  Actionable suggestion for the agent on how to recover from the error.
</ResponseField>

## Error Code Reference

### JSON-RPC Standard Errors

| Code   | Name           | Retryable | Recovery Hint                                         |
| ------ | -------------- | :-------: | ----------------------------------------------------- |
| -32700 | ParseError     |     No    | Fix the JSON syntax in the request                    |
| -32600 | InvalidRequest |     No    | Ensure the request follows JSON-RPC 2.0 structure     |
| -32601 | MethodNotFound |     No    | Check the method name against the protocol spec       |
| -32602 | InvalidParams  |     No    | Validate parameters against the method schema         |
| -32603 | InternalError  |     No    | Report as a bug -- this is an unexpected server error |

### Server State Errors

| Code   | Name               | Retryable | Recovery Hint                                                |
| ------ | ------------------ | :-------: | ------------------------------------------------------------ |
| -32000 | ServerError        |    Yes    | Generic server error -- retry after a delay                  |
| -32001 | NotInitialized     |     No    | Send an `initialize` request before calling any other method |
| -32002 | AlreadyInitialized |     No    | The connection is already initialized; proceed with commands |

### Browser Errors

| Code   | Name                  | Retryable | Recovery Hint                                                               |
| ------ | --------------------- | :-------: | --------------------------------------------------------------------------- |
| -32010 | BrowserNotLaunched    |     No    | Call `browser/launch` to start a browser                                    |
| -32011 | PageNotFound          |     No    | Call `page/list` to see available pages, or `page/create` to open a new one |
| -32023 | ContextNotFound       |     No    | The browser context does not exist                                          |
| -32024 | ResourceLimitExceeded |     No    | Max pages or contexts reached -- close some before creating new ones        |

### Element Errors

| Code   | Name              | Retryable | Recovery Hint                                                                        |
| ------ | ----------------- | :-------: | ------------------------------------------------------------------------------------ |
| -32012 | ElementNotFound   |    Yes    | Run `observe()` to refresh interactive elements, then retry with an updated selector |
| -32013 | ElementNotVisible |    Yes    | Scroll the element into view or wait for it to appear, then retry                    |
| -32014 | ElementNotEnabled |    Yes    | Wait for the element to become enabled (e.g., form validation), then retry           |
| -32020 | SelectorAmbiguous |     No    | Use a more specific selector (testId, CSS with nth-child, or role with exact name)   |

### Navigation and Action Errors

| Code   | Name             | Retryable | Recovery Hint                                           |
| ------ | ---------------- | :-------: | ------------------------------------------------------- |
| -32015 | NavigationFailed |    Yes    | Check the URL is valid and accessible, then retry       |
| -32016 | Timeout          |    Yes    | Increase timeout or wait for the page to finish loading |
| -32017 | TargetClosed     |     No    | The page or context was closed -- create a new one      |
| -32021 | ActionFailed     |   Varies  | Run `observe()` to verify element state, then retry     |

### Security and Approval Errors

| Code   | Name             | Retryable | Recovery Hint                                |
| ------ | ---------------- | :-------: | -------------------------------------------- |
| -32030 | ApprovalDenied   |     No    | The human operator denied this action        |
| -32040 | FrameNotFound    |     No    | The target frame does not exist on this page |
| -32041 | DomainNotAllowed |     No    | The domain is not in the server's allowlist  |

## Error Handling Patterns

### Retry with Backoff

For retryable errors, use the `retryAfterMs` hint:

```typescript theme={null}
try {
  await client.click(text("Submit"));
} catch (error) {
  if (error instanceof BAPError && error.retryable) {
    await sleep(error.retryAfterMs ?? 1000);
    // Re-observe then retry
    const obs = await client.observe();
    await client.click(obs.interactiveElements[0].selector);
  }
}
```

### Observe-Retry Pattern

The most common recovery pattern for element errors is to re-observe and retry:

```typescript theme={null}
try {
  await client.click(ref("@e5"));
} catch (error) {
  if (error.code === -32012) {
    // ElementNotFound
    const obs = await client.observe();
    // Find the element again using a different selector
    const target = obs.interactiveElements.find((el) => el.name === "Submit");
    if (target) await client.click(target.selector);
  }
}
```

### Structured Error Classes

Both SDKs provide typed error classes for precise error handling:

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import { BAPError, BAPElementNotFoundError, BAPTimeoutError } from "@browseragentprotocol/client";

    try {
      await client.click(role("button", "Submit"));
    } catch (error) {
      if (error instanceof BAPElementNotFoundError) {
        console.log("Recovery:", error.recoveryHint);
      } else if (error instanceof BAPTimeoutError) {
        console.log("Timed out after:", error.details?.timeout, "ms");
      }
    }
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from browseragentprotocol import BAPError, BAPElementNotFoundError, BAPTimeoutError

    try:
        await client.click(role("button", "Submit"))
    except BAPElementNotFoundError as e:
        print(f"Recovery: {e.recovery_hint}")
    except BAPTimeoutError as e:
        print(f"Timed out: {e.details}")
    except BAPError as e:
        print(f"Error {e.code}: {e.message}")
    ```
  </Tab>
</Tabs>
