grithdocs

Troubleshooting

The errors grith actually produces, what each one means, and the fix.

grith fails closed. Most of what goes wrong shows up as a refusal to start a session rather than a session that silently runs unsupervised, so the errors below are mostly grith telling you it will not proceed.

A session will not start

daemon not ready (version_mismatch)

grith exec is a thin client. It will not supervise anything without a daemon of exactly its own version, and it has no in-process fallback - if the daemon is not right, your command is never started at all. After an upgrade the old daemon is usually still listening:

terminal
$ grith daemon restart

The same refusal appears with other codes, each with its own remedy: port_owned_by_foreign_process (something else holds 3141), token_rejected and not_ready (restart), audit_quarantined and audit_read_only (below). Every one of them says No supervised session was started and then names the fix.

server.enabled is false in your configuration

Supervision needs the daemon for the session cap and the single audit writer, so with the server disabled grith exec refuses rather than supervising with weaker guarantees. Set server.enabled = true and retry.

The audit chain is quarantined

A session whose decisions cannot be verifiably recorded is not a supervised session, so the daemon admits none. Every existing record is preserved unmodified - nothing is rewritten at startup. Diagnose is read-only and is the one audit command that still works in this state:

terminal
$ grith audit diagnose
Chain status: writable

Full verification: chain is empty.

Segments: 1 (continuous history)

Duplicate sequences: none.
Sequence gaps: none.

Assessment: no integrity problems detected.

That is a healthy chain. A quarantined one names the reason instead, and reports forks, duplicate sequences and gaps.

ptrace is not permitted

grith needs CAP_SYS_PTRACE or Yama ptrace_scope set to 0 or 1. Ubuntu and Debian ship 1, which is fine; some hardened images use 2 or 3, which is not.

terminal
$ cat /proc/sys/kernel/yama/ptrace_scope

If it reads 2 or higher, either lower it (sudo sysctl kernel.yama.ptrace_scope=1, persisted in /etc/sysctl.d/) or run grith as a user holding CAP_SYS_PTRACE.

aarch64 supervision requires PTRACE_GET_SYSCALL_INFO (Linux kernel 5.3 or newer)

On arm64 grith reads the kernel's own syscall record; there is no fallback for older kernels, because the pre-5.3 paths are x86-shaped and would misclassify rather than fail. x86_64 needs 4.8 or newer.

The daemon

Port 3141 is in use by a process that is not a Grith daemon

grith will not evict a process it cannot identify as its own. Free the port, or move grith:

terminal
$ grith config set server.port 3142

grith daemon status distinguishes the three cases honestly - a grith daemon (naming its version), a foreign process, or nothing at all.

Config

Every command fails with supervisor.default_profile must be set

A hand-written sparse config.toml is the usual cause. Config layers merge as whole structures, so a file that omits a key still contributes that key's built-in default and overwrites the shipped value - and the built-in default for default_profile is empty, which fails validation.

terminal
$ grith --config config.toml config
Error: configuration invalid:
supervisor.default_profile must be set in TOML or via GRITH_SUPERVISOR_PROFILE

Start from what grith init writes, or use grith config set, which always writes a complete file. The same merge behaviour also silently raises supervisor.max_concurrent_sessions from 4 to 64 and changes the default model names, so it is worth avoiding for more than this one error.

Things that look broken and are not

The tool stopped and nothing is on screen

A permission prompt is waiting. In grith exec it is in the session window; if the session is headless there is no prompt and the call was denied instead. Note that only the calling thread is held - the rest of the tool keeps running, which is why a TUI carries on rendering while a decision is outstanding.

Everything that needed review was denied, with no prompt

That is the headless fail-closed path. See Running grith in CI.

grith canary add prints a token, grith canary list shows nothing

Working as built. The CLI mints into its own in-memory registry and exits. Durable registration means writing config/filters/canary.toml and restarting the daemon - see Setting up canary tokens.

DNS stopped working inside a --workspace-only session

The workspace boundary exempts reads of system runtime roots, including the resolver's runtime directories (/run/systemd/resolve/, /run/resolvconf/, /run/NetworkManager/, /run/nscd/). It deliberately does not exempt all of /run, because /run/user/<uid> holds the keyring, gnupg and ssh-agent sockets. A resolver reading from somewhere outside those will have those reads denied; the audit log names every path refused. Note also that the exemption is read-only - a write into a system path is still refused - and that the boundary covers the filesystem only, so network and process spawn are unaffected.

grith: command not found after installing

The installer puts the binary in ~/.local/bin unless you passed --global. Add it to PATH.

Getting help

Last updated: 2026-08-24Edit this page on GitHub →