Skip to content

Troubleshooting

Common issues and what to do about them.

Check these first

ravix --version        # is the binary on your PATH and built correctly?
ravix auth status      # are you logged in?
ravix daemon status    # is the daemon running?
ravix daemon logs -f   # what's it saying?

"api client (did you run ravix login?)"

No credentials in ~/.ravi/config.json. Run:

ravix auth login

…or just re-run ravix onboard, which does the login step as part of its flow.

"claude not found in PATH"

The service manager (launchd on macOS, systemd user on Linux) gives daemons a stripped PATH, so even if claude works in your terminal, the daemon can't see it.

ravix onboard handles this automatically by baking the resolved claude path into config.yaml under action.params.binary. If you're editing config by hand:

rules:
  - name: claude-run
    match:
      to: "inbox@raviapp.com"
    action:
      type: claude-run
      params:
        binary: "/opt/homebrew/bin/claude"   # ← full path required

Restart the daemon after editing.

Connection refused / timeout

The Ravi API is unreachable. Check:

  • Network connectivity: curl https://ravi.id
  • That ravix --version reports the right api: URL. If it's wrong, the binary was built with a stale API_URL. Rebuild:
make build API_URL=https://ravi.id

"path escapes root"

A write-to-file rule's path template rendered to a destination outside the configured root_dir. The daemon refuses for safety — template traversal is the vector here.

Fix by constraining the template. Common mistakes:

  • Using {{.To}} or {{.From}} unmodified when they could contain ../
  • Forgetting to anchor the path with {{.RootDir}}

Safe shape:

path: "{{.RootDir}}/inbox/{{.To}}/{{.ThreadIDSafe}}/{{.ID}}.sh"

Prefer {{.ID}} (monotonic integer) over {{.MessageIDHdr}} for filenames; the header contains <>@+ which is unsafe on every filesystem.

Daemon runs but no handlers fire

A few possibilities:

  1. Direction filter: the daemon only dispatches direction == "incoming". Outbound messages are ignored.
  2. First-run seeding: the very first poll after a fresh ~/.ravix/state.db records the current max message id as a cursor but emits zero events. This is intentional — prevents flooding handlers with backlog. Send a fresh message and it should fire.
  3. No rule matches: add a catch-all rule with no match fields at the bottom of rules: and a write-to-file action to see what's actually being received.
  4. Cursor stuck: delete ~/.ravix/state.db and restart. You'll re-seed (losing dedup history but not missing messages).

"ravi-hq/tap/ravi-cc has been disabled"

You're running brew install ravi-hq/tap/ravi-cc — that formula is the tombstoned old name. Use:

brew uninstall ravi-cc
brew install ravi-hq/tap/ravix

Daemon upgrade didn't take effect

ravix onboard is idempotent and always rebinds the service to the current binary — running it is safe. If you replaced the binary out of band (e.g. brew upgrade), re-run onboard so the service points at the new path:

ravix onboard

If you just want to bounce without onboarding:

ravix daemon stop && ravix daemon start

Still stuck?

File an issue with the output of ravix --version and the last 100 lines of ravix daemon logs:

github.com/ravi-hq/ravix/issues