sboxd 0.1.9

Policy-driven command runner for sandboxed dependency installation
Documentation
# Troubleshooting

## Diagnosis first: `sbox plan` and `sbox doctor`

Before debugging a failed run, always check:

```bash
sbox plan -- <your command>   # shows exactly what will be run and why
sbox doctor                   # checks backend health, signature verification, shim paths
```

---

## Container fails to start

### `lsetxattr /dev/null: operation not permitted`

**Cause:** Rootless Podman + SELinux enforcing on Fedora/RHEL. Occurs when Podman tries to apply SELinux labels to device nodes inside the container.

**Fix:** sbox automatically passes `--security-opt label=disable` when using `keep-id` user mapping. If you see this error, make sure you are running sbox 0.1.1 or later.

```bash
sbox --version
```

### `Error: crun: ... permission denied`

**Cause:** The host directory being mounted has permissions that the container user cannot read.

**Fix:** Check ownership of the workspace:

```bash
ls -la .
```

With rootless Podman and `keep-id`, the container runs as your host user. If files are owned by root or another user, reads will fail.

### `Error: image not found`

**Cause:** The image isn't pulled yet, or `pull_policy: never` is set.

**Fix:** Pull manually:

```bash
podman pull node:22-bookworm-slim
```

Or remove `pull_policy: never` from your config.

### Image digest mismatch

**Cause:** `image.digest` is set but the local image doesn't match — the image was re-pulled and the digest changed.

**Fix:** Update the digest in `sbox.yaml`:

```bash
podman inspect node:22-bookworm-slim --format '{{index .RepoDigests 0}}'
```

---

## npm / package manager errors

### `EROFS: read-only file system`

**Cause:** npm is trying to write to a file not in `writable_paths`.

Common cases:
- `package.json` or `package-lock.json` — npm wants to update them during install
- `.npmrc` in the workspace — excluded by `exclude_paths`, so the `/dev/null` mask is read-only

**Fix:** Add the path to `writable_paths`, or pass `--no-save` to npm:

```bash
sbox run -- npm install --no-save package-name
```

Or add `package-lock.json` to `writable_paths` if you want it updated:

```yaml
workspace:
  writable_paths:
    - node_modules
    - package-lock.json
```

### `ENOENT: no such file or directory` for a package tarball

**Cause:** You passed a host path to npm instead of the container path. The workspace is mounted at `/workspace`, not at its host path.

**Fix:** Use the container path:

```bash
# Wrong:
sbox run -- npm install /tmp/mypackage-1.0.0.tgz

# Right (if the tgz is in the workspace root):
sbox run -- npm install /workspace/mypackage-1.0.0.tgz
```

### npm output is empty / postinstall results missing

**Cause:** npm suppresses stdout/stderr from lifecycle scripts when they exit with code 0. Only failure output is shown.

**Fix:** If you need script output, write it to a file in `node_modules` (the only writable path) and read it from the host after the install. See the [adversarial test suite](../tests/adversarial/) for an example of this pattern.

---

## Network errors

### `ENETUNREACH` or `connection refused` during install

**Cause:** The install profile has `network: off` but the package manager needs the internet to download packages.

**Fix:** Use `network: on` with `network_allow` to allow only the registry:

```yaml
profiles:
  install:
    network: on
    network_allow:
      - "*.npmjs.org"
```

See [network.md](network.md) for details.

### DNS resolution fails for an allowed domain

**Cause:** `network_allow` resolves hostnames at plan time and injects IPs into `--add-host`. If the IP changes between plan and run (CDN rotation), the injected address may be stale.

**Fix:** Add the specific IP manually, or accept that `network_allow` is best-effort for CDN-backed registries. For critical CI pipelines, use a fixed private registry with a stable IP.

### `network_allow` has no effect

**Cause:** `network: off` is set in the same profile. `network_allow` only applies when `network: on`.

**Fix:**

```yaml
profiles:
  install:
    network: on          # must be on for network_allow to work
    network_allow:
      - registry.npmjs.org
```

---

## Credential / environment issues

### Token is present in the container even though it's in `deny`

**Cause:** The token is in `environment.set` AND `environment.deny`. In sbox 0.1.0 and earlier, `set` bypassed `deny`. Fixed in 0.1.1.

**Fix:** Upgrade to sbox 0.1.1 or later. `deny` now takes precedence over `set`.

### Host env var is not reaching the container

**Cause:** Only vars listed in `pass_through` are forwarded. Everything else is stripped.

**Fix:** Add the variable to `pass_through`:

```yaml
environment:
  pass_through:
    - MY_VAR
```

Or inject it explicitly with `set`:

```yaml
environment:
  set:
    MY_VAR: my-value
```

---

## Config errors

### `sbox.yaml` not found

**Cause:** sbox walks up from the current directory looking for `sbox.yaml`. If none is found, it errors.

**Fix:** Run `sbox init --interactive` in your project root, or specify the config explicitly:

```bash
sbox --config /path/to/sbox.yaml run -- npm install
```

### `unknown profile`

**Cause:** `sbox exec <profile> -- <command>` references a profile that doesn't exist in `sbox.yaml`.

**Fix:** Check available profiles with:

```bash
sbox plan -- <command>
```

The `profile source` line shows which profile was selected.

### Strict mode refusing execution

```
error: strict security: image is not pinned to a digest
error: strict security: lockfile not found
error: strict security: sensitive variable passed through
```

**Fix:** Address each complaint:
- Pin the image: `image.digest: sha256:...`
- Add the lockfile or run `npm install` first to generate it
- Remove the sensitive var from `pass_through` or add it to `deny`

---

## Shim issues

### Shim is not intercepting commands

**Cause:** The real binary appears before the shim directory in `PATH`.

**Fix:** Make sure `~/.local/bin` (or wherever shims are installed) comes before the real binary:

```bash
export PATH="$HOME/.local/bin:$PATH"
which npm   # should show ~/.local/bin/npm
```

### Shim runs on a project without `sbox.yaml`

**Cause:** This is expected — shims fall through to the real binary when no `sbox.yaml` is found. No sandbox is applied.

---

## Performance

### Container startup is slow

Rootless Podman adds ~0.5–1s of startup overhead per invocation. For repeated commands, enable reusable sessions:

```yaml
runtime:
  reuse_container: true
```

Or at the profile level:

```yaml
profiles:
  dev:
    reuse_container: true
```

A named container is started once and reused for all subsequent `sbox run` calls in that workspace. Clean it up with:

```bash
sbox clean
```

### Image pull is slow on first run

Pull the image separately before running:

```bash
podman pull node:22-bookworm-slim
```

Subsequent runs use the local image without pulling.