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

# Errors & Metrics

> C SDK error handling and metrics

## Error Codes

### BoxliteErrorCode

All API functions return `BoxliteErrorCode` to indicate success or failure type:

```c theme={null}
typedef enum BoxliteErrorCode {
    Ok = 0,               // Success
    Internal = 1,         // Internal error
    NotFound = 2,         // Resource not found
    AlreadyExists = 3,    // Resource already exists
    InvalidState = 4,     // Invalid state for operation
    InvalidArgument = 5,  // Invalid argument
    Config = 6,           // Configuration error
    Storage = 7,          // Storage error
    Image = 8,            // Image error
    Network = 9,          // Network error
    Execution = 10,       // Execution error
    Stopped = 11,         // Resource stopped
    Engine = 12,          // Engine error
    Unsupported = 13,     // Unsupported operation
    Database = 14,        // Database error
    Portal = 15,          // Portal/communication error
    Rpc = 16,             // RPC error
} BoxliteErrorCode;
```

### Error Code Reference

| Code              | Name                | Value | Description                                           |
| ----------------- | ------------------- | ----- | ----------------------------------------------------- |
| `Ok`              | Success             | 0     | Operation completed successfully                      |
| `Internal`        | Internal Error      | 1     | An internal error occurred                            |
| `NotFound`        | Not Found           | 2     | The requested resource was not found                  |
| `AlreadyExists`   | Already Exists      | 3     | The resource already exists                           |
| `InvalidState`    | Invalid State       | 4     | The resource is in an invalid state for the operation |
| `InvalidArgument` | Invalid Argument    | 5     | An invalid argument was provided                      |
| `Config`          | Configuration Error | 6     | A configuration error occurred                        |
| `Storage`         | Storage Error       | 7     | A storage error occurred                              |
| `Image`           | Image Error         | 8     | An image-related error occurred                       |
| `Network`         | Network Error       | 9     | A network error occurred                              |
| `Execution`       | Execution Error     | 10    | A command execution error occurred                    |
| `Stopped`         | Stopped             | 11    | The resource is stopped                               |
| `Engine`          | Engine Error        | 12    | A VM engine error occurred                            |
| `Unsupported`     | Unsupported         | 13    | The operation is not supported                        |
| `Database`        | Database Error      | 14    | A database error occurred                             |
| `Portal`          | Portal Error        | 15    | A portal/communication error occurred                 |
| `Rpc`             | RPC Error           | 16    | An RPC error occurred                                 |

### CBoxliteError

Detailed error information for debugging:

```c theme={null}
typedef struct CBoxliteError {
    BoxliteErrorCode code;  // Error code for programmatic handling
    char* message;          // Detailed message (NULL if none)
} CBoxliteError;
```

<Note>
  Always initialize `CBoxliteError` with zero: `CBoxliteError error = {0};`. The struct is stack-allocated, but the `message` field points to heap memory that must be freed with `boxlite_error_free()`.
</Note>

## Error Handling Functions

### boxlite\_error\_free

Free error struct (message only - struct itself is stack-allocated).

```c theme={null}
void boxlite_error_free(CBoxliteError* error);
```

Safe to call with NULL. After calling, the `message` field is set to NULL.

## Error Handling Patterns

### Pattern 1: Basic Check

```c theme={null}
CBoxliteError error = {0};
BoxliteErrorCode code = boxlite_simple_new("alpine:3.19", 0, 0, &box, &error);

if (code != Ok) {
    fprintf(stderr, "Error %d: %s\n", error.code, error.message);
    boxlite_error_free(&error);
    return 1;
}
```

### Pattern 2: Switch on Error Code

```c theme={null}
BoxliteErrorCode code = boxlite_get(runtime, "box-id", &box, &error);

switch (code) {
    case Ok:
        // Success - use box
        break;
    case NotFound:
        fprintf(stderr, "Box not found\n");
        break;
    case InvalidState:
        fprintf(stderr, "Box in invalid state\n");
        break;
    default:
        fprintf(stderr, "Error %d: %s\n", error.code, error.message);
}

boxlite_error_free(&error);
```

### Pattern 3: Retry Logic

```c theme={null}
int retries = 3;
for (int i = 0; i < retries; i++) {
    code = boxlite_simple_new("alpine:3.19", 0, 0, &box, &error);
    if (code == Ok) break;

    fprintf(stderr, "Retry %d/%d: %s\n", i+1, retries, error.message);
    boxlite_error_free(&error);

    if (code == InvalidArgument || code == Unsupported) {
        break;  // Non-retryable errors
    }
    sleep(1);  // Backoff
}
```

<Tip>
  Some error codes like `InvalidArgument` and `Unsupported` indicate permanent failures that should not be retried. Check the error code before retrying.
</Tip>

### Pattern 4: Cleanup on Error

```c theme={null}
CBoxliteRuntime* runtime = NULL;
CBoxHandle* box = NULL;
CBoxliteError error = {0};

if (boxlite_runtime_new(NULL, NULL, &runtime, &error) != Ok) {
    fprintf(stderr, "Runtime error: %s\n", error.message);
    boxlite_error_free(&error);
    return 1;
}

const char* options = "{"
    "\"rootfs\":{\"Image\":\"alpine:3.19\"},"
    "\"env\":[],\"volumes\":[],\"network\":\"Isolated\",\"ports\":[]"
"}";

if (boxlite_create_box(runtime, options, &box, &error) != Ok) {
    fprintf(stderr, "Box error: %s\n", error.message);
    boxlite_error_free(&error);
    boxlite_runtime_free(runtime);  // Clean up runtime before exit
    return 1;
}

// Use box...

boxlite_runtime_free(runtime);  // Frees runtime and all boxes
```

## Metrics

### boxlite\_runtime\_metrics

Get runtime-wide metrics as JSON.

```c theme={null}
BoxliteErrorCode boxlite_runtime_metrics(
    CBoxliteRuntime* runtime,
    char** out_json,
    CBoxliteError* out_error
);
```

#### Parameters

| Parameter   | Type               | Description                                                         |
| ----------- | ------------------ | ------------------------------------------------------------------- |
| `runtime`   | `CBoxliteRuntime*` | Runtime instance                                                    |
| `out_json`  | `char**`           | Output: JSON string (caller must free with `boxlite_free_string()`) |
| `out_error` | `CBoxliteError*`   | Output: error information                                           |

#### Example Output

```json theme={null}
{
  "boxes_created_total": 10,
  "boxes_failed_total": 0,
  "num_running_boxes": 2,
  "total_commands_executed": 42,
  "total_exec_errors": 1
}
```

#### Runtime Metrics Fields

| Field                     | Type    | Description                                       |
| ------------------------- | ------- | ------------------------------------------------- |
| `boxes_created_total`     | integer | Total number of boxes created since runtime start |
| `boxes_failed_total`      | integer | Total number of box creation failures             |
| `num_running_boxes`       | integer | Current number of running boxes                   |
| `total_commands_executed` | integer | Total commands executed across all boxes          |
| `total_exec_errors`       | integer | Total command execution errors                    |

#### Example

```c theme={null}
char* metrics_json = NULL;
CBoxliteError error = {0};

if (boxlite_runtime_metrics(runtime, &metrics_json, &error) == Ok) {
    printf("Runtime metrics: %s\n", metrics_json);
    boxlite_free_string(metrics_json);
} else {
    fprintf(stderr, "Error: %s\n", error.message);
    boxlite_error_free(&error);
}
```

### boxlite\_box\_metrics

Get per-box metrics as JSON.

```c theme={null}
BoxliteErrorCode boxlite_box_metrics(
    CBoxHandle* handle,
    char** out_json,
    CBoxliteError* out_error
);
```

#### Parameters

| Parameter   | Type             | Description                                                         |
| ----------- | ---------------- | ------------------------------------------------------------------- |
| `handle`    | `CBoxHandle*`    | Box handle                                                          |
| `out_json`  | `char**`         | Output: JSON string (caller must free with `boxlite_free_string()`) |
| `out_error` | `CBoxliteError*` | Output: error information                                           |

#### Example Output

```json theme={null}
{
  "cpu_percent": 5.2,
  "memory_bytes": 12582912,
  "commands_executed_total": 10,
  "exec_errors_total": 0,
  "bytes_sent_total": 1024,
  "bytes_received_total": 2048,
  "total_create_duration_ms": 1234,
  "guest_boot_duration_ms": 567
}
```

#### Box Metrics Fields

| Field                      | Type    | Description                          |
| -------------------------- | ------- | ------------------------------------ |
| `cpu_percent`              | float   | Current CPU usage percentage         |
| `memory_bytes`             | integer | Current memory usage in bytes        |
| `commands_executed_total`  | integer | Total commands executed in this box  |
| `exec_errors_total`        | integer | Total execution errors in this box   |
| `bytes_sent_total`         | integer | Total network bytes sent             |
| `bytes_received_total`     | integer | Total network bytes received         |
| `total_create_duration_ms` | integer | Time taken to create the box (ms)    |
| `guest_boot_duration_ms`   | integer | Time taken for guest OS to boot (ms) |

#### Example

```c theme={null}
char* metrics_json = NULL;
CBoxliteError error = {0};

if (boxlite_box_metrics(box, &metrics_json, &error) == Ok) {
    printf("Box metrics: %s\n", metrics_json);
    boxlite_free_string(metrics_json);
} else {
    fprintf(stderr, "Error: %s\n", error.message);
    boxlite_error_free(&error);
}
```

### Complete Metrics Example

```c theme={null}
#include <stdio.h>
#include "boxlite.h"

int main() {
    CBoxliteRuntime* runtime = NULL;
    CBoxHandle* box = NULL;
    CBoxliteError error = {0};
    char* json = NULL;

    // Setup runtime and box
    boxlite_runtime_new(NULL, NULL, &runtime, &error);

    const char* options = "{"
        "\"rootfs\":{\"Image\":\"alpine:3.19\"},"
        "\"env\":[],\"volumes\":[],\"network\":\"Isolated\",\"ports\":[]"
    "}";
    boxlite_create_box(runtime, options, &box, &error);

    // Execute some commands
    int exit_code = 0;
    boxlite_execute(box, "echo", "[\"hello\"]", NULL, NULL, &exit_code, &error);
    boxlite_execute(box, "ls", "[\"/\"]", NULL, NULL, &exit_code, &error);

    // Check runtime metrics
    if (boxlite_runtime_metrics(runtime, &json, &error) == Ok) {
        printf("Runtime metrics:\n%s\n\n", json);
        boxlite_free_string(json);
    }

    // Check box metrics
    if (boxlite_box_metrics(box, &json, &error) == Ok) {
        printf("Box metrics:\n%s\n", json);
        boxlite_free_string(json);
    }

    // Cleanup
    boxlite_runtime_free(runtime);
    return 0;
}
```
