gitbutlerapp/gitbutler · error
file monitor stopped
Error message
file monitor stopped
What it means
FileMonitorHandle::flush sends a Flush command over a channel to the monitor worker thread. If the send fails, the receiver has been dropped, meaning the monitor thread has exited/shut down and can no longer emit pending events. The error is a channel-closed surrogate for 'monitor is dead'.
Solutions
- Check whether the monitor was shut down before calling flush; keep the monitor alive for the handle's lifetime.
- Treat this error as benign during shutdown and ignore/log it.
- Recreate the file monitor if continued watching is needed.
- Check logs for an earlier monitor-thread panic (e.g. watch setup failure) that caused the exit.
Example fix
// before
handle.flush()?; // Err even if you just want pending events
// after
if let Err(e) = handle.flush() {
tracing::warn!("file monitor unavailable: {e}"); // benign at shutdown
} Defensive patterns
Strategy: fallback
Try / catch
match handle.flush() {
Ok(()) => {},
Err(e) => log::warn!("file monitor stopped, skipping flush: {e}"), // benign during shutdown
} Prevention
- Keep the monitor instance alive as long as its handle is used.
- Order shutdown: drop handles before stopping the monitor.
- Log and ignore flush errors during teardown rather than propagating.
When it happens
Trigger: Calling flush() after the file monitor was stopped or its worker thread panicked/exited; flushing during app shutdown after cmd_tx's receiver was dropped.
Common situations: Calling flush on a handle whose monitor was dropped; race between shutdown and a UI/editor action requesting a flush; watch teardown due to a fatal watch error earlier.
Related errors
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/145c16b05e2f2f6b.
Report an issue: GitHub.
Appendix: source
Thrown at crates/gitbutler-filemonitor/src/file_monitor.rs:62
const FLUSH_AFTER_EMPTY: u32 = 3;
enum Command {
Flush,
}
/// Handle for a running file monitor spawned with [`spawn()`].
///
/// Dropping this handle will stop the monitor as soon as it tries to send the next event, failing as there is no receiver.
pub struct FileMonitorHandle {
cmd_tx: std::sync::mpsc::Sender<Command>,
}
impl FileMonitorHandle {
/// Request that pending filesystem events are emitted immediately.
pub fn flush(&self) -> Result<()> {
self.cmd_tx
.send(Command::Flush)
.map_err(|_| anyhow!("file monitor stopped"))
}
}
const ENV_WATCH_MODE: &str = "GITBUTLER_WATCH_MODE";
/// Control how the filesystem watch should be established.
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
pub enum WatchMode {
/// Recursively watch the worktree (and an extra git-dir if the repo uses
/// a linked worktree with a git-dir outside the worktree), using [`notify::RecursiveMode::Recursive`].
Legacy,
/// Ignore-aware watch plan: non-recursive watches of non-ignored worktree directories,
/// plus explicit git-dir watches and dynamic watch additions for newly created directories.
/// Each directory is watched with [`notify::RecursiveMode::NonRecursive`].
Modern,
/// Automatically pick a mode based on platform heuristics.
///
#[default]View on GitHub (pinned to 58e5313667)