spacedriveapp/spacedrive · error

PersistentEventHandler not connected to FsWatcherService

Error message

PersistentEventHandler not connected to FsWatcherService

What it means

PersistentEventHandler::start mirrors the ephemeral handler: after the double-start guard it clones the FsWatcherService from RwLock<Option<...>> and errors when None. The comment in the source notes locations can be registered before start(); the same leniency does not apply to the watcher itself, which must already be connected when start runs.

Source

Thrown at core/src/ops/indexing/handlers/persistent.rs:222

		Ok(())
	}

	/// Get all registered locations
	pub async fn locations(&self) -> Vec<LocationMeta> {
		self.locations.read().await.values().cloned().collect()
	}

	/// Start the event handler
	pub async fn start(&self) -> Result<()> {
		if self.is_running.swap(true, Ordering::SeqCst) {
			warn!("PersistentEventHandler is already running");
			return Ok(());
		}

		let fs_watcher = self.fs_watcher.read().await.clone();
		let Some(fs_watcher) = fs_watcher else {
			return Err(anyhow::anyhow!(
				"PersistentEventHandler not connected to FsWatcherService"
			));
		};

		debug!("Starting PersistentEventHandler");

		// Create workers for all registered locations AND register paths with FsWatcher
		// This is critical: locations may have been added before start() was called,
		// when the FsWatcher wasn't connected yet, so we need to register them now.
		let locations: Vec<LocationMeta> = self.locations.read().await.values().cloned().collect();
		for meta in &locations {
			self.ensure_worker(meta.clone()).await?;

			// Register the path with the OS-level watcher (may have been skipped during add_location)
			debug!(
				"Registering path {} with FsWatcher for location {}",
				meta.root_path.display(),
				meta.id

View on GitHub (pinned to 6dfeccf211)

Solutions

  1. Attach the FsWatcherService before calling start() on the persistent handler
  2. Verify watcher service initialization succeeded in daemon startup logs before handlers start
  3. If watcher-less operation is intended, downgrade to a warning and skip subscription
Defensive patterns

Strategy: validation

Validate before calling

// Check the watcher slot before start
if handler.fs_watcher_slot_filled().await {
    handler.start().await?;
} else {
    tracing::warn!("PersistentEventHandler not wired to a watcher; skipping start");
}

Try / catch

if let Err(e) = persistent_handler.start().await {
    if e.to_string().contains("not connected to FsWatcherService") {
        // connect the watcher, then retry start() once
    }
}

Prevention

When it happens

Trigger: Calling start() on a PersistentEventHandler whose fs_watcher slot was never populated; watcher service failed to initialize during daemon startup; handler started after the watcher was dropped during shutdown.

Common situations: Daemon startup ordering bugs; feature-flagged watcher disabled but handlers still started; tests constructing the handler directly without a watcher.

Related errors


AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16). Data as JSON: /api/errors/28d84231e28bc07b. Report an issue: GitHub.