Reference
Troubleshooting
Most problems are a rule naming the wrong program, a host the policy does not list, or a change nobody applied. Start with the log.
fenzi doctor fails
| Check | What to do |
|---|---|
| Runtime not found | Install the pinned version doctor names, then run it again. |
| Version outside the pinned range | Install the version doctor names. We move the pin after reading each upstream release. |
| Gateway not connected | Usually the container runtime is not running, for example after the machine restarts. doctor names it. Run fenzi setup: it starts the runtime you have, then the gateway. See Container runtimes. On colima, also see below. |
| No compute driver | The gateway found no Docker, Podman, or VM to run sandboxes in. On colima, see below. |
| Automatic approval is set for every sandbox | Run fenzi doctor --fix. It removes that gateway-wide setting and nothing else. |
| Sandbox settings | The gateway turns off the audit log or agent requests for every sandbox, and that overrides what run sets. Run fenzi doctor --fix to remove the gateway-wide value. |
| Policy prover not installed | The prover, openshell-prover, ships with the runtime's Homebrew, Debian, and RPM packages. Reinstall the runtime from one of them. |
| No image builder | Install Docker or Podman. Fenzi builds agent images with one of them, even when sandboxes run on the MicroVM driver. |
Container runtimes
The gateway starts sandboxes in a container runtime, or in a MicroVM. When the gateway is not connected, fenzi setup looks for the runtimes below, says which are installed and which are running, and offers to start a stopped one with that runtime's own command. Then it restarts the gateway. If the gateway config names a Docker socket, setup only offers the runtime that serves it.
| Runtime | Setup starts it with | With the gateway |
|---|---|---|
| Docker Desktop, Mac | open -a Docker | Named by the upstream docs. Not run by us yet. |
| colima, Mac | colima start | Tested. Needs three gateway settings, below. |
| OrbStack, Mac | open -a OrbStack | Not tested, and not named upstream. |
| Rancher Desktop, Mac | open -a "Rancher Desktop" | Not tested, and not named upstream. |
| Docker Engine, Linux | sudo systemctl start docker, or systemctl --user start docker when rootless | Named by the upstream docs. Not run by us yet. |
| Podman 5, Linux | systemctl --user start podman.socket | Named by the upstream docs. Not run by us yet. |
With no runtime installed on a Mac with Homebrew, setup offers to install colima and the Docker command line with brew install colima docker, and shows that command first. Docker Desktop is the other documented choice; install it yourself, then run fenzi setup again. On Linux, install Docker Engine 28 or later, or Podman 5, from your distribution. A runtime setup does not list can still work if the gateway is configured for it; setup then only offers to restart the gateway.
colima on a Mac
The runtime's Mac instructions assume Docker Desktop. With colima, the gateway needs to know where colima's Docker socket is. Sandboxes also run inside colima's VM, where localhost is the VM, not your Mac, so they need another address to reach the gateway. When the gateway is not connected and colima is running, setup offers to set it up:
fenzi setupChoose Set up the gateway for colima. Setup shows the file it will write, ~/.config/openshell/gateway.toml, and asks you to confirm. Then it restarts the gateway with Homebrew services and waits for it to connect. With your user name in the socket path, the file is:
[openshell]
version = 2
[openshell.gateway]
compute_driver = "docker"
[openshell.drivers.docker]
socket_path = "/Users/you/.colima/default/docker.sock"
grpc_endpoint = "https://host.docker.internal:17670"Setup only writes the file when there is none. If you already have a gateway.toml, it is not changed; add those three settings to it yourself and restart the gateway. The gateway's certificate already covers host.docker.internal, so nothing else changes. fenzi doctor --fix does not configure colima.
The sandbox does not start
The policy check failed. run exits with code 2 and prints the prover's result. If it is exceeds_boundary, the example shows which action is too wide. Narrow the rule. See The check before start.
Filesystem rules could not be enforced. Fenzi requires them, so the sandbox does not start without them. The kernel needs Landlock ABI v3 or later. On a Mac, that means the kernel of the Linux VM that Docker or the MicroVM driver runs, not macOS.
Something else. The sandbox is kept when the agent exits, so fenzi log --raw reads everything it logged. fenzi stop removes it afterwards.
A blocked host looks like a network error
When a host is not in the policy, the sandbox refuses the connection before any request is sent. The agent sees Could not resolve host or Could not connect, the same as a network outage. The reason is only in the log:
fenzi log --deny --since 5mA reason of policy_dns_ineligible or transparent_tcp_policy_denied means the host is not in the policy.
If the host should be allowed, approve the request the agent or the sandbox filed (fenzi requests), or add the host to fenzi.yaml. Hosts that are in the policy get a clearer answer: a request the rule does not allow comes back as HTTP 403 with policy_denied.
The agent gives up instead of asking
- No
guideline when the run started. Claude Code, Codex, OpenCode, and Grok get the guide today. An agent started without it does not file requests itself. Approve the request the sandbox drafted from the blocked call, then tell the agent to retry. - The agent's own permission check stopped it. Agents ask before running commands, including the ones that file a request and wait for the answer. Allow them when the agent asks. The sandbox still decides what the request grants, and a person still approves it.
- Claude Code refused the command itself. In auto mode, Claude's own check can turn a command down before it reaches the sandbox. Fenzi starts Claude in manual mode unless you pass
--permission-mode. If you chose auto, switch back with Shift+Tab or start it withfenzi run claude --permission-mode manual.
Claude Code says it has no key
On its first start in a sandbox, Claude Code asks whether to use the API key it found in the environment, with No marked as recommended. If you chose No, it has no key. The value it found is the sandbox's placeholder; the real key is added outside the sandbox. Claude keeps its answer in its settings inside that sandbox. Quit it, end the sandbox with fenzi stop so its changes come back, and start a new one with fenzi run. The new sandbox asks again; choose Yes.
A host in the policy is still denied
Read the deny in the log. It names the program the sandbox saw.
- The rule names a different program. Rules match the program that opens the connection, by its real path.
pipruns on the Python interpreter andnpmruns on Node, so the rule must name the interpreter. Inside the sandbox,readlink -f $(which python3)shows the real path. - The program changed. The sandbox remembers each program the first time it connects, and blocks it if the file at that path changes later. After updating an agent or a tool, start a new sandbox.
- The request breaks a request rule. A
read-onlyhost allows onlyGET,HEAD, andOPTIONS. APOSTis denied withpolicy_denied. - The host name differs. The sandbox has no DNS search domains. Use the exact name the policy lists.
Package installs fail
npm. npm audit sends a POST, which a read-only rule blocks. Agent images turn audit off. If you run npm with your own config, use npm install --no-audit.
pip. Downloads come from files.pythonhosted.org. The default policy lists it. If you replaced the default, list it too.
A private registry. Add its host to fenzi.yaml with read-only access.
The agent cannot reach its model
- Run
fenzi key listto see whether a key is stored for the agent. If not, runfenzi key set claude. - If you rotated the key, run
fenzi key set claudeto replace the stored one. New sandboxes use it. - If Claude Code says
Unable to connect to Anthropic services, your CLI predates the rule forplatform.claude.com, which Claude Code checks on first start. Update the CLI. - If the log shows a credential error, the request went to a host the key is not bound to. Do not widen the network rule. The key's endpoints come from the agent's profile.
The agent's changes do not appear
They are staged, not applied; you chose to keep them for later, or the run had no terminal to ask in. From the project folder, run fenzi diff, then fenzi apply. If apply refuses, a file changed in your repo while the agent worked. It lists the files. Resolve them and run it again.
Files matched by .gitignore were never copied in, so the agent did not see or change them. Neither was .git, so the sandbox has no Git history and only file changes come back.
The log has gaps
The gateway keeps a limited buffer of recent events, and loses it if the gateway restarts. When the agent exits, Fenzi waits for the last events to arrive (they come in batches over a few seconds) and saves them before it asks whether to delete the sandbox. If the gateway restarted during the run, or a sandbox was deleted another way, those events are gone. On Team the console shows that hole: the sandbox, and the span between the last decision it has and the next one. It does not fill the missing lines in.
Blocked file writes are never in the log, and a reset line is not a refusal. See What the log does not hold and reset lines. fenzi log --raw shows everything the sandbox logged, including settings changes.
Connections drop after an approval
When network rules change, the sandbox closes open WebSocket connections. Clients that reconnect recover on their own. Plain HTTP requests are not affected.
Still stuck
Run fenzi doctor and fenzi log --since 30m, and open an issue on github.com/fenzi-inc/fenzi/issues with the output of both. Neither contains your code or your keys. Read them before you post them anyway: issues there are public.
For a security problem, such as a way out of the sandbox, report it privately to security@fenzi.dev. Do not post details in public.