Skip to main content

Error Codes

v0.2.0 introduces structured error handling with error codes and detailed messages.

BoxliteErrorCode

All API functions return BoxliteErrorCode to indicate success or failure type:
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

CodeNameValueDescription
OkSuccess0Operation completed successfully
InternalInternal Error1An internal error occurred
NotFoundNot Found2The requested resource was not found
AlreadyExistsAlready Exists3The resource already exists
InvalidStateInvalid State4The resource is in an invalid state for the operation
InvalidArgumentInvalid Argument5An invalid argument was provided
ConfigConfiguration Error6A configuration error occurred
StorageStorage Error7A storage error occurred
ImageImage Error8An image-related error occurred
NetworkNetwork Error9A network error occurred
ExecutionExecution Error10A command execution error occurred
StoppedStopped11The resource is stopped
EngineEngine Error12A VM engine error occurred
UnsupportedUnsupported13The operation is not supported
DatabaseDatabase Error14A database error occurred
PortalPortal Error15A portal/communication error occurred
RpcRPC Error16An RPC error occurred

CBoxliteError

Detailed error information for debugging:
typedef struct CBoxliteError {
    BoxliteErrorCode code;  // Error code for programmatic handling
    char* message;          // Detailed message (NULL if none)
} CBoxliteError;
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().

Error Handling Functions

boxlite_error_free

Free error struct (message only - struct itself is stack-allocated).
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

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

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

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
}
Some error codes like InvalidArgument and Unsupported indicate permanent failures that should not be retried. Check the error code before retrying.

Pattern 4: Cleanup on Error

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.
BoxliteErrorCode boxlite_runtime_metrics(
    CBoxliteRuntime* runtime,
    char** out_json,
    CBoxliteError* out_error
);

Parameters

ParameterTypeDescription
runtimeCBoxliteRuntime*Runtime instance
out_jsonchar**Output: JSON string (caller must free with boxlite_free_string())
out_errorCBoxliteError*Output: error information

Example Output

{
  "boxes_created_total": 10,
  "boxes_failed_total": 0,
  "num_running_boxes": 2,
  "total_commands_executed": 42,
  "total_exec_errors": 1
}

Runtime Metrics Fields

FieldTypeDescription
boxes_created_totalintegerTotal number of boxes created since runtime start
boxes_failed_totalintegerTotal number of box creation failures
num_running_boxesintegerCurrent number of running boxes
total_commands_executedintegerTotal commands executed across all boxes
total_exec_errorsintegerTotal command execution errors

Example

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.
BoxliteErrorCode boxlite_box_metrics(
    CBoxHandle* handle,
    char** out_json,
    CBoxliteError* out_error
);

Parameters

ParameterTypeDescription
handleCBoxHandle*Box handle
out_jsonchar**Output: JSON string (caller must free with boxlite_free_string())
out_errorCBoxliteError*Output: error information

Example Output

{
  "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

FieldTypeDescription
cpu_percentfloatCurrent CPU usage percentage
memory_bytesintegerCurrent memory usage in bytes
commands_executed_totalintegerTotal commands executed in this box
exec_errors_totalintegerTotal execution errors in this box
bytes_sent_totalintegerTotal network bytes sent
bytes_received_totalintegerTotal network bytes received
total_create_duration_msintegerTime taken to create the box (ms)
guest_boot_duration_msintegerTime taken for guest OS to boot (ms)

Example

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

#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;
}