Skip to main content
All three SDKs surface typed errors so you can match on specific failure modes instead of parsing strings. Rust has an Error enum, TypeScript has MicrosandboxError with a type discriminant, and Python uses an exception hierarchy.

Matching errors

use microsandbox::{Sandbox, Error};

async fn get_or_create(name: &str) -> Result<Sandbox, Error> {
    match Sandbox::get(name).await {
        Ok(handle) => handle.start().await,
        Err(Error::SandboxNotFound(_)) => {
            Sandbox::builder(name).image("python:3.12").create().await
        }
        Err(e) => Err(e),
    }
}

match sb.exec("python", ["script.py"]).await {
    Ok(output) if output.status().success => {
        println!("{}", output.stdout()?);
    }
    Ok(output) => {
        eprintln!("Exit {}: {}", output.status().code, output.stderr()?);
    }
    Err(Error::ExecTimeout) => eprintln!("Timed out"),
    Err(Error::Runtime(msg)) => eprintln!("Runtime: {msg}"),
    Err(e) => return Err(e),
}

Resource cleanup

Sandboxes hold compute resources, so release them when done. In Rust, Drop handles cleanup when the sandbox goes out of scope. In TypeScript and Python, use try/finally or context managers.
use microsandbox::Sandbox;

// Sandbox implements Drop, so resources are released when `sb` goes out of scope.
// For explicit control, call stop() or kill().
{
    let sb = Sandbox::builder("temp")
        .image("python:3.12")
        .create()
        .await?;

    let output = sb.exec("python", ["-c", "print('hello')"]).await?;
} // sb is dropped here, resources are cleaned up