docs/book/src/ops/troubleshooting.md
Common failure modes, in the order you're likely to encounter them.
First stop for any issue:
<div class="os-tabs-src">zeroclaw doctor
Runs a series of checks and prints a summary. Most of what follows is the detailed version of what doctor flags.
cargo not foundcurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Or pass --prebuilt to install.sh / setup.bat to skip Rust entirely.
Install the baseline toolchain for your distro, then re-run ./install.sh:
sudo apt install build-essential pkg-config
sudo dnf group install development-tools && sudo dnf install pkg-config
sudo pacman -S base-devel
Full per-distro list: Setup → Linux.
Building ZeroClaw from source is memory-hungry, mostly during the final link. install.sh already adapts to this automatically when it builds from source:
{{#include ../_snippets/hardware-lowmem-lto.md}}
If you still run out of memory, or you are not building through install.sh:
./install.sh --prebuilt skips the toolchain and downloads from GitHub Releases.cargo build --profile release-fast (more codegen parallelism, lighter link) or --profile ci (thin LTO, fastest/lowest-memory).CARGO_BUILD_JOBS=1 cargo build --release --locked.For the Raspberry Pi specifics, see Raspberry Pi setup → build.
The Matrix E2EE stack (matrix-sdk, ruma, vodozemac) and TLS/crypto native deps (aws-lc-sys, ring) are the main cost. Opt out if you don't need them:
cargo build --release --locked --no-default-features --features "default-lean"
Or check what's happening:
<div class="os-tabs-src">cargo check --timings
# report at target/cargo-timings/cargo-timing.html
zeroclaw: command not found after installcargo install puts binaries in ~/.cargo/bin/. Add to PATH:
export PATH="$HOME/.cargo/bin:$PATH"
Persist in your shell profile.
zeroclaw quickstart does not have a --force flag, it intentionally leaves an existing install alone. To run a fresh quickstart on a stale install, delete the directory and start over:
rm -rf ~/.zeroclaw
zeroclaw quickstart
Or, to edit a single stale field instead of wiping everything, use zeroclaw config set <key>=<value> directly.
Homebrew installs prefer $HOMEBREW_PREFIX/var/zeroclaw/ (so brew services works) while the default config dir is ~/.zeroclaw/. Set ZEROCLAW_WORKSPACE to the Homebrew path before running quickstart so the two paths line up:
export ZEROCLAW_WORKSPACE="$HOMEBREW_PREFIX/var/zeroclaw"
zeroclaw quickstart
Or manually symlink once:
<div class="os-tabs-src">ln -s "$HOMEBREW_PREFIX/var/zeroclaw" ~/.zeroclaw
Symptoms:
model_provider = "openai.<alias>" points at a Codex entry, but runs still feel misconfiguredapi_key / api_url (those belong on the provider entry, not at the file root)provider streaming failed, falling back to non-streaming chatChecks (substitute <alias> with the configured agent alias from [agents.<alias>]):
For an OpenAI Codex subscription, set requires_openai_auth = true on the provider alias and leave api_key unset; the runtime uses the stored Codex login. Get the subscription credential from the vendor's own login flow. See Provider Configuration → OAuth and subscription auth for the full credential model. Then test:
zeroclaw agent -a <alias> -m "hello"
Notes:
requires_openai_auth = true on the alias (with api_key unset) selects the subscription path; surround it with the canonical agent + risk profile from the Minimal working example.api_key / uri on the alias entry are only needed for custom OpenAI-compatible gateways or other explicit endpoint overrides.Check journald / the platform log (see Logs & observability) for the actual error. Common causes:
zeroclaw config list to print resolved values, zeroclaw config schema to see the expected shape42617; change [gateway] port or free the portsystemctl --user status zeroclaw shows the last exit. If it's a config error, it stopped restarting (exit 2) and you need to fix the config. If it's a panic, the unit retries every 10 s.
Enable debug logging and catch the next failure:
<div class="os-tabs-src">zeroclaw service stop
RUST_LOG=debug zeroclaw daemon
curl -sv http://localhost:42617/health
If connection refused: daemon isn't running, or it's bound to a different interface. Check [gateway] host / port in config.
If 403 / 401: pairing not completed or token expired. Run the pairing flow again.
terminated by other getUpdates requestTwo processes are polling the same bot token. Telegram only allows one poller at a time.
Fix: stop all but one zeroclaw daemon / zeroclaw channel start using that token.
Discord tokens expire if you regenerate them in the Developer Portal. Slack bot tokens don't expire but can be revoked. Check the bot is still installed in the target workspace/guild.
For either:
<div class="os-tabs-src">zeroclaw channel doctor discord
zeroclaw channel doctor slack
If you re-onboarded without keeping device keys, the homeserver sees a new device that hasn't been verified. Re-verify from another logged-in client, or reset the key store:
<div class="os-tabs-src">rm -rf ~/.zeroclaw/workspace/matrix-crypto
# re-run pairing flow on next channel start
Most often an auth failure, provider rotated the password or the app-password expired. Check:
<div class="os-tabs-src">journalctl --user -u zeroclaw -n 200 | grep -i imap
systemctl status ollama (Linux), brew services list (macOS)localhost:11434 doesn't reach the host; use host.docker.internal or the host's LAN IPAPI key invalid or expired. Regenerate at the provider's dashboard, update in [providers.models.<name>] api_key, restart the service.
If using OAuth (sk-ant-oat*), the OAuth token may have expired. OAuth-issued tokens are longer-lived but not infinite. Re-authenticate.
Expected behaviour at Supervised autonomy for unknown commands. Either:
[autonomy] allowed_commandsFull if you trust the contextSee Security → Autonomy levels.
docker pull <image> for whatever you have configured under [security.sandbox].image (default: alpine:latest)docker infoallow_devicesPlaywright downloads Chromium (~150 MB) on first launch. Let it finish. If it keeps hanging, check disk space and proxy config.
zeroclaw service start
zeroclaw service status
Use zeroclaw service logs to tail the installed service logs. Add --follow to stream new entries or --lines <count> to change how much history is shown. If the wrapper is unavailable or you need to inspect the platform directly, use:
journalctl --user -u zeroclaw.service -flog stream --predicate 'process == "zeroclaw"'zeroclaw daemon directly in a terminal, use that foreground output instead of service log commands.If that succeeds interactively but the service dies in the background, it's almost always config or permissions, read the journal:
<div class="os-tabs-src">journalctl --user -u zeroclaw --since "5 minutes ago"
The service and CLI may resolve config differently if they run as different users or with different env vars. Force-print the path the daemon sees:
<div class="os-tabs-src">zeroclaw config list
If the paths differ between zeroclaw config list (as you) and the service (as its user), either:
ZEROCLAW_CONFIG_DIR in the service unit's Environment=Gather diagnostics and file an issue:
<div class="os-tabs-src">zeroclaw --version
zeroclaw doctor
zeroclaw channel doctor
journalctl --user -u zeroclaw --since "1 hour ago" > zeroclaw-log.txt
Sanitise zeroclaw-log.txt (redact channel tokens if any slipped through, they shouldn't) and attach it to the issue. See Contributing → Communication for where.