box.exec(...) does not raise on a non-zero exit code. It returns an ExecResult and leaves the decision to you. The BoxliteError hierarchy covers the other failures.
Which failures actually raise
Practical takeaway: catch in the order specific subclasses (ExecError/TimeoutError/ParseError) ->BoxliteError-> standardRuntimeError/Error, otherwise low-level failures escape.
Handling all four in one place
The most concise, directly runnable robust execution pattern: run a command, check the exit code, raiseExecError on failure, and catch every possible
failure.
Parameters and Returns
Exception hierarchy
All SDK-layer errors inherit fromBoxliteError, so except BoxliteError /
instanceof BoxliteError catches every error the SDK actively raises.
Note: Python’sboxlite.TimeoutErroris a subclass ofBoxliteError, not Python’s built-inbuiltins.TimeoutError. If you import both, use an alias to disambiguate.
ExecError constructor parameters (Python)
ExecError constructor parameters (Node, positional)
ExecResult (the return value of box.exec(...), not an exception)
This is the core of robust error handling: check the return value first, then
decide whether to raise.
Note: thestdout/stderrabove apply to theExecResultreturned by the high-levelSimpleBox.exec(...). If you use the nativeawait (await box.exec(...)).wait()path, itsExecResulthas onlyexit_codeanderror_message--- accessing.stdout/.stderrraisesAttributeError. To get output, useSimpleBox.exec.
Recommended wrapper: a run_checked that raises ExecError
Wrap “check the exit code + raise ExecError” into a helper so that the upper
layer only needs a single try/except style.
Distinguishing a timeout from a general failure
Key fact: whenSimpleBox.exec(timeout=...)hits a timeout it does not raiseboxlite.TimeoutError--- it terminates the process on the sandbox side withSIGTERMand returnsExecResult(exit_code == -15). So in the example below,sleep 5 / timeout=1.0reachesprint("exit_code:", result.exit_code)and prints-15; theexcept TimeoutErrorbranch does not fire. Always detect a timeout by checkingresult.exit_code(negative = terminated by signal); do not rely onexcept TimeoutError.boxlite.TimeoutErrormainly models a higher-level SDK “waited for a readiness state and timed out” (e.g. waiting for desktop/browser readiness), not anexeccommand timeout.
Troubleshooting
You try/except ExecError, but a command failure is not caught
Cause: box.exec(...) does not raise on a non-zero command exit; it
returns ExecResult(exit_code != 0).
Fix: after running, check result.exit_code (Node: result.exitCode) and
raise ExecError(...) yourself on failure, or use the run_checked wrapper
above.
A missing command (spawn failure) raises in both SDKs
Python: callingbox.exec(...) for a nonexistent command raises
RuntimeError, with a message like
internal error: spawn_failed: internal error: build failed: ... executable '<cmd>' not found in $PATH.
It does not return an ExecResult and is not a BoxliteError ---
isinstance(err, BoxliteError) is False. So catch it with
except RuntimeError.
Node: SimpleBox.exec throws a bare Error on spawn failure, with a
message containing spawn_failed, and err instanceof BoxliteError === false.
Fix: on Python, catch spawn failures with except RuntimeError (placed after
except BoxliteError); on Node, catch the non-BoxliteError bare Error in the
else branch. Do not assume a missing command returns an ExecResult or is a
BoxliteError.
from boxlite import TimeoutError collides with Python’s built-in TimeoutError
Cause: boxlite.TimeoutError is a subclass of BoxliteError --- the same
name as builtins.TimeoutError but a different class.
Fix: import with an alias:
Passing the volume string "ro"/"rw" raises TypeError
Error message: TypeError: argument 'volumes': 'str' object cannot be cast as 'bool'.
Cause: the SDK’s third volume element is the bool read_only (True =
read-only / False = read-write), not the CLI’s "ro"/"rw" string.
Fix:
Note: only the CLI’s-v host:box:rosyntax usesro/rwstrings; the SDK API uses a bool, so do not confuse them.
Image pull failure / network instability
Error message:RuntimeError (not BoxliteError).
Fix: catch with except RuntimeError and retry (retry needs network access
and a correctly spelled image reference). Always be online for the first run.
Box fails to start: no virtualization
Cause: BoxLite needs Linux + KVM/hardware virtualization; macOS uses the built-in Hypervisor.framework (no /dev/kvm required); WSL2 needs KVM with the user in thekvm group. Without virtualization, the box cannot start.
Symptom: entering async with SimpleBox(...) or the first exec raises
RuntimeError (Python) / Error (Node); the process itself does not crash and
can be caught and degraded with try/except.
Fix: run in an environment that supports virtualization; in CI, confirm
/dev/kvm is mounted and permissioned.
C SDK: the command failure code and the API call error code are two distinct concepts
In the C SDK you likewise distinguish two layers: the API call itself returns aBoxliteErrorCode (such as NotFound=2, InvalidArgument=5), while the command
process’s exit code is reported separately in ExecResult.exit_code --- an API
return of Ok does not mean the command succeeded. See
examples/c/04_error_handling.c:

