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

> Learn to debug microsandbox issues. Use CLI, SDK, or Rust logs to diagnose VM boot, network policy, and file system operations. Enable debug logging for faster resolution.

- Repository: [Super Rad Company/microsandbox](https://github.com/superradcompany/microsandbox)
- Tags: how-to-guide
- Published: 2026-08-20

---

**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)](https://github.com/superradcompany/microsandbox/blob/main/crates/cli/src/main.rs), the argument parsing handles this delegation.

```bash

# 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)](https://github.com/superradcompany/microsandbox/blob/main/crates/metrics-collector/bin/main.rs), where env-var overrides apply before the subscriber is installed.

```bash
RUST_LOG=debug cargo run --example sandbox_demo

```

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

```rust
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)](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)](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)](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

```text
~/.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

```bash

# 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`](https://github.com/superradcompany/microsandbox/blob/main/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)](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)](https://github.com/superradcompany/microsandbox/blob/main/crates/network/lib/policy.rs).

```bash

# 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:

```bash
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)](https://github.com/superradcompany/microsandbox/blob/main/crates/utils/lib/process.rs). Correlate `child_reaping` events with `sandbox::stop` spans:

```bash
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)](https://github.com/superradcompany/microsandbox/blob/main/crates/metrics-collector/bin/main.rs)) exports timing data:

```bash

# 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)](https://github.com/superradcompany/microsandbox/blob/main/sdk/rust/src/lib.rs), the `Sandbox` type exposes detailed error chains:

```rust
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

```python
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

```ts
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`:

```go
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)](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)](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)](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)](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)](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)](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)](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)](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)](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`](https://github.com/superradcompany/microsandbox/blob/main/msb.json), [`runtime.json`](https://github.com/superradcompany/microsandbox/blob/main/runtime.json), and [`metrics.json`](https://github.com/superradcompany/microsandbox/blob/main/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`](https://github.com/superradcompany/microsandbox/blob/main/sandbox.rs), policy in [`policy.rs`](https://github.com/superradcompany/microsandbox/blob/main/policy.rs), subscriber setup in [`metrics-collector/bin/main.rs`](https://github.com/superradcompany/microsandbox/blob/main/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`](https://github.com/superradcompany/microsandbox/blob/main/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)](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)](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.