How to Debug Issues in microsandbox: A Complete Guide to CLI, SDK, and Runtime Diagnostics

Enable debug logging in microsandbox using msb --log-level debug, set MICROSANDBOX_LOG=debug for SDKs, or use RUST_LOG=debug for Rust code, then inspect structured JSON logs in ~/.microsandbox/logs/ to trace VM boot sequences, network policy enforcement, and file-system operations.

The microsandbox project by SuperRad Company runs untrusted workloads inside lightweight micro-VMs. Debugging these sandboxed environments requires visibility across three distinct layers: the CLI tool, language SDKs, and the runtime agent. All layers funnel diagnostics through a unified structured tracing system based on the tracing crate, writing JSON-lines to log files you can filter with standard tools.


Enable Debug Logging in microsandbox

CLI Debugging with msb

The msb CLI accepts a --log-level flag that forwards the level to the runtime via the MICROSANDBOX_LOG environment variable. In [crates/cli/src/main.rs](https://github.com/superradcompany/microsandbox/blob/main/crates/cli/src/main.rs), the argument parsing handles this delegation.


# Maximum verbosity for every traced event

msb --log-level debug run python -- python -c "print('hi')"

Valid levels include error, warn, info, debug, and trace. The debug level captures VM boot sequences, image pulling, and RPC messages without overwhelming output.


SDK Debugging: Rust

The Rust SDK honors the standard RUST_LOG environment variable. The tracing subscriber initialization occurs in [crates/metrics-collector/bin/main.rs](https://github.com/superradcompany/microsandbox/blob/main/crates/metrics-collector/bin/main.rs), where env-var overrides apply before the subscriber is installed.

RUST_LOG=debug cargo run --example sandbox_demo

You can also set the variable programmatically before initializing the subscriber:

std::env::set_var("RUST_LOG", "microsandbox=debug,network=trace");
tracing_subscriber::fmt::init();

SDK Debugging: Python, TypeScript, and Go

All non-Rust SDKs read the MICROSANDBOX_LOG environment variable during native startup:

SDK Setup location Usage
Python [sdk/python/__init__.py](https://github.com/superradcompany/microsandbox/blob/main/sdk/python/__init__.py) MICROSANDBOX_LOG=debug python my_script.py
TypeScript [sdk/node-ts/src/index.ts](https://github.com/superradcompany/microsandbox/blob/main/sdk/node-ts/src/index.ts) MICROSANDBOX_LOG=debug node my_script.js
Go [sdk/go/sandbox.go](https://github.com/superradcompany/microsandbox/blob/main/sdk/go/sandbox.go) MICROSANDBOX_LOG=debug go run main.go or ms.WithLogLevel(ctx, "debug")

Locate and Filter microsandbox Log Files

By default, logs write to ~/.microsandbox/logs/ as JSON-lines. The structure enables precise filtering with jq.

Log File Organization

~/.microsandbox/logs/
├── msb.json              # CLI-level events

├── runtime.json          # Runtime and agentd events

├── metrics.json          # Metrics collector output

└── sandbox-<name>.json   # Per-sandbox trace (when --trace enabled)

jq Filtering Examples


# All agentd messages from the runtime

jq 'select(.target == "agentd")' ~/.microsandbox/logs/runtime.json

# Network policy rejections

jq 'select(.fields.message | contains("policy::reject"))' ~/.microsandbox/logs/runtime.json

# Boot timing events

jq 'select(.span.name == "vm_boot")' ~/.microsandbox/logs/metrics.json

The JSON format includes standard tracing fields: timestamp, level, target, span, and custom fields with structured data.


Debug Common microsandbox Issues

Sandbox Fails to Start

  1. Enable CLI debug: msb --log-level debug run …
  2. Inspect runtime.json for vm::boot span events
  3. Check for KVM/WHP/Apple Hypervisor availability errors

Look for these specific error patterns in [crates/runtime/lib/sandbox.rs](https://github.com/superradcompany/microsandbox/blob/main/crates/runtime/lib/sandbox.rs):

  • "kvm": "permission denied on /dev/kvm" → Add user to kvm group
  • "whp": "Windows Hypervisor Platform not available" → Enable in Windows Features
  • "image_pull": "manifest not found" → Verify image name and registry access

Network Requests Blocked

Network policy enforcement emits trace events from [crates/network/lib/policy.rs](https://github.com/superradcompany/microsandbox/blob/main/crates/network/lib/policy.rs).


# Find rejected connections

jq 'select(.fields | has("policy_action") and .policy_action == "reject")' \
  ~/.microsandbox/logs/runtime.json

Key fields to examine:

  • policy_rule – The rule that matched the request
  • host and port – The destination that was denied
  • sandbox_id – Which sandbox initiated the request

File-System Mount Errors

Mount operations use the mount:: span namespace. Search for:

jq 'select(.target | contains("mount"))' ~/.microsandbox/logs/runtime.json

Common errors in the output:

  • "error": "cannot open source path" – Verify host path exists and is readable
  • "error": "volume already in use" – Check for orphaned sandbox processes
  • "error": "incompatible fs type" – Confirm the guest kernel supports the filesystem

Unexpected Process Termination

Process lifecycle logging resides in [crates/utils/lib/process.rs](https://github.com/superradcompany/microsandbox/blob/main/crates/utils/lib/process.rs). Correlate child_reaping events with sandbox::stop spans:

jq 'select(.span.name | test("(child_reaping|sandbox_stop)"))' \
  ~/.microsandbox/logs/runtime.json | jq -s 'sort_by(.timestamp)'

Look for signal numbers, exit codes, and core-dump indicators in the fields object.


Performance Debugging

The metrics collector (binary in [crates/metrics-collector/bin/main.rs](https://github.com/superradcompany/microsandbox/blob/main/crates/metrics-collector/bin/main.rs)) exports timing data:


# Boot time breakdown

jq 'select(.name == "boot_time_ms")' ~/.microsandbox/logs/metrics.json

# Image download vs VM init latency

jq 'select(.name | test("(image_pull|vm_init)"))' ~/.microsandbox/logs/metrics.json

Code Examples for microsandbox Debugging

Rust: Capturing SDK Errors with Context

From [sdk/rust/src/lib.rs](https://github.com/superradcompany/microsandbox/blob/main/sdk/rust/src/lib.rs), the Sandbox type exposes detailed error chains:

use microsandbox::Sandbox;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    std::env::set_var("RUST_LOG", "debug");
    tracing_subscriber::fmt::init();

    let sandbox = Sandbox::builder("demo")
        .image("python")
        .cpus(1)
        .memory(512)
        .create()
        .await?;

    // The {:#} format shows the full error chain with source locations
    match sandbox.exec("python", ["-c", "raise Exception('boom')"]).await {
        Ok(out) => println!("{}", out.stdout()?),
        Err(e) => eprintln!("exec failed: {:#}", e),
    }

    sandbox.stop().await?;
    Ok(())
}

The {:#} debug format on anyhow::Error includes spantraces when tracing-error is enabled.


Python: Debug-Ready Script

import os
import asyncio
from microsandbox import Sandbox, logger

async def main():
    os.environ["MICROSANDBOX_LOG"] = "debug"
    logger.setLevel("DEBUG")  # Forwards to Python's logging module

    sandbox = await Sandbox.create(
        "py-demo",
        image="python",
        cpus=1,
        memory=512,
    )

    try:
        out = await sandbox.exec("python", ["-c", "print('hello')"])
        print(out.stdout_text)
    except Exception as e:
        logger.exception("Sandbox execution failed")
        raise
    finally:
        await sandbox.stop()

asyncio.run(main())

TypeScript: Enabling Per-Process Tracing

import { Sandbox } from "microsandbox";

process.env.MICROSANDBOX_LOG = "debug";

(async () => {
  const sandbox = await Sandbox.builder("ts-demo")
    .image("python")
    .cpus(1)
    .memory(512)
    .create();

  try {
    const out = await sandbox.exec("python", ["-c", "print('hello')"]);
    console.log(out.stdout());
  } catch (e) {
    console.error("Sandbox error:", e);
    throw e;
  } finally {
    await sandbox.stop();
  }
})();

Go: Context-Aware Log Levels

The Go SDK supports per-context log levels via ms.WithLogLevel:

package main

import (
  "context"
  "log"
  ms "github.com/superradcompany/microsandbox/sdk/go"
)

func main() {
  ctx := context.Background()
  ctx = ms.WithLogLevel(ctx, "debug") // Sets MICROSANDBOX_LOG for subprocesses

  sandbox, err := ms.CreateSandbox(ctx, "go-demo",
    ms.WithImage("python"),
    ms.WithCPUs(1),
    ms.WithMemory(512),
  )
  if err != nil {
    log.Fatalf("create sandbox: %v", err)
  }
  defer sandbox.Stop(ctx)

  out, err := sandbox.Exec(ctx, "python", []string{"-c", "print('hi')"})
  if err != nil {
    log.Fatalf("exec: %v", err)
  }
  log.Printf("Output: %s", out.Stdout())
}

Key Source Files for microsandbox Debugging

File Debugging Relevance
[crates/cli/src/main.rs](https://github.com/superradcompany/microsandbox/blob/main/crates/cli/src/main.rs) --log-level flag parsing and forwarding
[crates/metrics-collector/bin/main.rs](https://github.com/superradcompany/microsandbox/blob/main/crates/metrics-collector/bin/main.rs) tracing_subscriber initialization; RUST_LOG processing
[crates/utils/lib/log_text.rs](https://github.com/superradcompany/microsandbox/blob/main/crates/utils/lib/log_text.rs) JSON log formatting and field serialization
[crates/runtime/lib/sandbox.rs](https://github.com/superradcompany/microsandbox/blob/main/crates/runtime/lib/sandbox.rs) VM lifecycle: boot, stop, error propagation
[crates/network/lib/policy.rs](https://github.com/superradcompany/microsandbox/blob/main/crates/network/lib/policy.rs) Network policy enforcement events
[sdk/rust/src/lib.rs](https://github.com/superradcompany/microsandbox/blob/main/sdk/rust/src/lib.rs) SDK error wrapping and agent RPC handling
[sdk/python/__init__.py](https://github.com/superradcompany/microsandbox/blob/main/sdk/python/__init__.py) Python logger configuration
[sdk/node-ts/src/index.ts](https://github.com/superradcompany/microsandbox/blob/main/sdk/node-ts/src/index.ts) TypeScript SDK tracing setup
[sdk/go/sandbox.go](https://github.com/superradcompany/microsandbox/blob/main/sdk/go/sandbox.go) Go SDK entry points and context helpers

Quick Debug Checklist for microsandbox

  • Set debug log level: RUST_LOG=debug, MICROSANDBOX_LOG=debug, or msb --log-level debug
  • Reproduce the issue with logging enabled
  • Locate JSON logs in ~/.microsandbox/logs/
  • Filter with jq using select(.target), select(.span.name), or select(.level == "ERROR")
  • Correlate timestamps across msb.json, runtime.json, and metrics.json
  • Verify host hypervisor: kvm-ok (Linux), Windows Features (WHP), System Info (macOS)
  • Cross-reference error events with source files above
  • Include filtered log excerpts when reporting issues

Summary

  • Three layers produce debug output: CLI (msb), language SDKs, and runtime/agent — all using the structured tracing system
  • Environment variables control verbosity: RUST_LOG for Rust, MICROSANDBOX_LOG for all SDKs, --log-level for CLI
  • JSON-lines format in ~/.microsandbox/logs/ enables precise filtering with jq by target, span, level, or message content
  • Common issues map to specific log patterns: VM boot failures, network policy::reject, mount errors, and process termination signals
  • Source code reference grounds debugging in actual implementation: lifecycle in sandbox.rs, policy in policy.rs, subscriber setup in metrics-collector/bin/main.rs

Frequently Asked Questions

What is the difference between RUST_LOG and MICROSANDBOX_LOG?

RUST_LOG is the standard tracing crate environment variable, used primarily for Rust-native code and the metrics-collector binary. MICROSANDBOX_LOG is the cross-language variable that all SDKs (Python, TypeScript, Go) read to configure their underlying tracing integration. When using Rust, prefer RUST_LOG; for other languages or mixed environments, use MICROSANDBOX_LOG. Both accept the same level syntax: debug, microsandbox=trace, or target-specific filters like network=debug,runtime=info.

How do I debug a sandbox that crashes immediately on start?

Enable msb --log-level debug run … and inspect ~/.microsandbox/logs/runtime.json for spans named vm::boot or image_pull. Check for hypervisor availability errors (/dev/kvm permissions on Linux, WHP on Windows, Hypervisor.framework on macOS). The boot_time_ms metric in metrics.json helps distinguish between slow image pulls and VM initialization failures. Cross-reference any error messages with [crates/runtime/lib/sandbox.rs](https://github.com/superradcompany/microsandbox/blob/main/crates/runtime/lib/sandbox.rs) for the exact failure path.

Can I redirect microsandbox logs to stdout instead of files?

The default subscriber in metrics-collector writes to rolling JSON files for structured analysis. For development, override the subscriber in your application code: tracing_subscriber::fmt::fmt().with_writer(std::io::stdout).init() in Rust, or set MICROSANDBOX_LOG_FORMAT=pretty if supported by your SDK version. The CLI flag --log-level also affects stderr verbosity in real-time, though full JSON traces always route to the log directory for persistence.

Why are my network requests being blocked inside the sandbox?

Network policy enforcement emits policy::reject events from [crates/network/lib/policy.rs](https://github.com/superradcompany/microsandbox/blob/main/crates/network/lib/policy.rs). Filter logs with jq 'select(.fields.policy_action == "reject")' to see the denied host, port, and matching rule. Default policies often block all outbound traffic; configure explicit allow rules in your sandbox configuration or use the network: open preset for debugging purposes only.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →