{"record":{"id":"28d84231e28bc07b","repo":"spacedriveapp/spacedrive","slug":"persistenteventhandler-not-connected-to-fswatchers","errorCode":null,"errorMessage":"PersistentEventHandler not connected to FsWatcherService","messagePattern":"PersistentEventHandler not connected to FsWatcherService","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/src/ops/indexing/handlers/persistent.rs","lineNumber":222,"sourceCode":"\n\t\tOk(())\n\t}\n\n\t/// Get all registered locations\n\tpub async fn locations(&self) -> Vec<LocationMeta> {\n\t\tself.locations.read().await.values().cloned().collect()\n\t}\n\n\t/// Start the event handler\n\tpub async fn start(&self) -> Result<()> {\n\t\tif self.is_running.swap(true, Ordering::SeqCst) {\n\t\t\twarn!(\"PersistentEventHandler is already running\");\n\t\t\treturn Ok(());\n\t\t}\n\n\t\tlet fs_watcher = self.fs_watcher.read().await.clone();\n\t\tlet Some(fs_watcher) = fs_watcher else {\n\t\t\treturn Err(anyhow::anyhow!(\n\t\t\t\t\"PersistentEventHandler not connected to FsWatcherService\"\n\t\t\t));\n\t\t};\n\n\t\tdebug!(\"Starting PersistentEventHandler\");\n\n\t\t// Create workers for all registered locations AND register paths with FsWatcher\n\t\t// This is critical: locations may have been added before start() was called,\n\t\t// when the FsWatcher wasn't connected yet, so we need to register them now.\n\t\tlet locations: Vec<LocationMeta> = self.locations.read().await.values().cloned().collect();\n\t\tfor meta in &locations {\n\t\t\tself.ensure_worker(meta.clone()).await?;\n\n\t\t\t// Register the path with the OS-level watcher (may have been skipped during add_location)\n\t\t\tdebug!(\n\t\t\t\t\"Registering path {} with FsWatcher for location {}\",\n\t\t\t\tmeta.root_path.display(),\n\t\t\t\tmeta.id","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/spacedriveapp/spacedrive/blob/6dfeccf2113039e35f2ce735f945e70dc3e4ea45/core/src/ops/indexing/handlers/persistent.rs#L204-L240","documentation":"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.","triggerScenarios":"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.","commonSituations":"Daemon startup ordering bugs; feature-flagged watcher disabled but handlers still started; tests constructing the handler directly without a watcher.","solutions":["Attach the FsWatcherService before calling start() on the persistent handler","Verify watcher service initialization succeeded in daemon startup logs before handlers start","If watcher-less operation is intended, downgrade to a warning and skip subscription"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Check the watcher slot before start\nif handler.fs_watcher_slot_filled().await {\n    handler.start().await?;\n} else {\n    tracing::warn!(\"PersistentEventHandler not wired to a watcher; skipping start\");\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = persistent_handler.start().await {\n    if e.to_string().contains(\"not connected to FsWatcherService\") {\n        // connect the watcher, then retry start() once\n    }\n}","preventionTips":["Register locations after the watcher is connected, or rely on start()'s re-registration pass","Verify watcher service initialization in startup logs before handlers run","Downgrade to a warn-and-skip when watcher-less operation is an accepted mode"],"tags":["indexing","watcher","lifecycle","wiring","change-detection"],"backgroundTag":null,"analyzedSha":"6dfeccf2113039e35f2ce735f945e70dc3e4ea45","analyzedAt":"2026-08-16T11:26:17.074Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}