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

> ## Agent Instructions
> These docs cover learner integrations through Hosted Lab Pages, the SDK, and the REST API. Content management is outside this integration scope.
> Read the setup page for the chosen approach before implementing it. Keep organization API keys and hosted mint secrets on the server.
> The public SDK is coming soon. Check the SDK quickstart for current availability. Do not invent installation commands or direct readers to a private package.
> Cybr provides completion tracking and CTF verification. The integrating platform decides whether to award points.

# Error handling

> Handle retries, unknown outcomes, and safe browser responses.

## Catch SDK errors

```ts theme={null}
import { CybrLabsError } from '@cybr/labs-sdk'

try {
  await cybr.deployments.launch({ labId, learnerId })
} catch (error) {
  if (error instanceof CybrLabsError) {
    console.error(error.code, error.status, error.backendCode)
  }
  throw error
}
```

`code` describes the SDK error category. `backendCode` retains the API error code for diagnostics.

## Retry reads and writes differently

The SDK retries transient GET errors. A failed GET can be repeated without a new launch or submission.

A network error or timeout after a write has an unknown outcome. The server can finish the action before the response fails.

Do not automatically repeat launches after unknown outcomes. Retain the deployment ID from successful launches and reconcile your application state.

Repeated completion responses require deduplication in your application. The [completion guide](/guides/completion-and-scoring) explains them.

## Rate limits

If the error is `rate_limited`, show the `retryAfter` wait in your interface. The value is in seconds.

If the error is `concurrency_limited`, show that the organization has no free deployment slots. Repeated launch requests do not release slots.

## Terminal startup

`createTerminalSession()` retries `CONTAINER_STARTING` within its startup deadline. Other terminal failures return to your application.

An ended or disabled terminal requires a different action, not an automatic reconnect loop.

## Browser responses

Return only the fields your interface requires:

```ts theme={null}
function publicError(error: unknown) {
  if (error instanceof CybrLabsError) {
    return {
      code: error.code,
      message: error.message,
      retryAfter: error.retryAfter
    }
  }
  return { code: 'unknown', message: 'The request failed.' }
}
```

Keep raw causes and diagnostic fields on the server. Logs must not contain API keys, lab outputs, or terminal credentials.

See the [error reference](/reference/errors) for categories.
