Skip to content

Troubleshooting

Find your symptom below. Three commands answer most questions first:

Terminal window
runwisp validate # is the config valid?
runwisp status # is the daemon up, and is it running the current config?
runwisp list # which tasks exist, and when do they fire?
  1. Run runwisp validate. It checks runwisp.toml exactly like startup does and reports the key, line, and column of each error.
  2. Check the port. The default is 127.0.0.1:9477. If something holds it (often a RunWisp you forgot about), runwisp stop the old daemon or pick another --port.
  3. On a headless box, use runwisp daemon. Bare runwisp opens the TUI and offers to create a config. runwisp daemon exits with an error instead, which is what an init system needs.

Check these in order:

  1. It has no cron. Then it only runs when you start it. runwisp list shows the schedule RunWisp parsed.
  2. The daemon doesn’t have your edit yet. See the next section.
  3. The timezone is different from what you expect. Cron uses the task’s timezone, then [daemon] timezone, then the host’s zone. See Scheduling.
  4. The previous run is still going. See Runs pile up.

If a manual trigger is refused, the task has manual_trigger = false.

The daemon never watches the file. Apply edits yourself:

Terminal window
runwisp reload # everything else
runwisp restart # [daemon] TLS, metrics, allow_station_dispatch

If the reload is rejected, nothing changed at all. The error tells you why: a config error, or a setting that needs a restart. See Reload & restart.

If you didn’t set a password, the daemon generated one. Print it:

Terminal window
runwisp password
  • If runwisp password refuses, the daemon uses RUNWISP_PASSWORD. Get it from where you set it. For an installed service, that’s the drop-in file service install printed (see Autostart).
  • If the login answers 429, you hit the rate limit. Wait a few minutes.
  • To set your own password, see The password. For local development only, you can turn auth off.
  • Old runs disappear over time: retention. keep_runs and keep_for delete old runs per task; [storage] max_size deletes the oldest runs across all tasks.
  • The start or middle of a long run is gone: the run hit log_max_size, and log_on_full decided what to drop.
  • Output stops with Log output stopped: disk space critically low: free disk fell below min_free_space.

See Run logs.

on_overlap decides what happens when a run is due while the previous one is still going:

  • queue (default): the new run waits. A slow task on a fast schedule builds a backlog.
  • skip: the new run is recorded as skipped and doesn’t start. A manual trigger can look like it did nothing.
  • kill: the running one is stopped and the new one starts.

A run that seems stuck forever may have no timeout. See Overlapping runs.

A service keeps restarting, or is stuck in FATAL

Section titled “A service keeps restarting, or is stuck in FATAL”

A service that keeps dying at start is marked FATAL after restart_attempts, and RunWisp stops trying. Open its run history: each failed attempt has its exit code and output. If a service starts fine but is counted as failed too soon, look at healthy_after.

See When a service can’t start.

  1. Is the channel routed? A [notifiers.<id>] block alone sends nothing. Add its id to a task’s notify, global_notifiers, or a [[route]].
  2. Did delivery fail? A permanent failure puts a notify.delivery_failed entry in the bell in the Web UI and TUI.
  3. Did you reload? The daemon picks up edits to [notify], [notifiers.*], [[route]], and template_path files only after runwisp reload.

See Notifications.

Turn on debug logging and watch a run:

Terminal window
runwisp daemon --log-level debug

A task that never fires and a task that fires and dies right away look very different in the daemon log.

To report a bug, attach runwisp status --json and the daemon log around the failure to an issue.