fix: skip watcher on home

kujtimiihoxha created

Change summary

internal/lsp/watcher/global_watcher.go | 29 +++++++++++++++++++++++----
1 file changed, 24 insertions(+), 5 deletions(-)

Detailed changes

internal/lsp/watcher/global_watcher.go 🔗

@@ -12,6 +12,7 @@ import (
 	"github.com/charmbracelet/crush/internal/config"
 	"github.com/charmbracelet/crush/internal/csync"
 	"github.com/charmbracelet/crush/internal/fsext"
+	"github.com/charmbracelet/crush/internal/home"
 	"github.com/charmbracelet/crush/internal/lsp/protocol"
 	"github.com/fsnotify/fsnotify"
 )
@@ -91,16 +92,31 @@ func (gw *global) unregister(name string) {
 // events for all files within watched directories. Multiple calls with the same workspace
 // are safe since fsnotify handles directory deduplication internally.
 func Start() error {
+	cfg := config.Get()
+	root := cfg.WorkingDir()
+
+	// Skip file watching entirely when running in home directory
+	// Home directories typically contain too many files and directories
+	// which can overwhelm the file watcher and cause "too many open files" errors
+	if root == home.Dir() {
+		slog.Info("lsp watcher: Skipping file watcher in home directory to prevent resource exhaustion", "path", root)
+		return nil
+	}
+
 	gw := instance()
 
+	// If watcher creation failed, skip file watching entirely
+	if gw.watcher == nil {
+		slog.Warn("lsp watcher: File watcher not available, file watching disabled")
+		return nil
+	}
+
 	// technically workspace root is always the same...
 	if gw.started.Load() {
 		slog.Debug("lsp watcher: watcher already set up, skipping")
 		return nil
 	}
 
-	cfg := config.Get()
-	root := cfg.WorkingDir()
 	slog.Debug("lsp watcher: set workspace directory to global watcher", "path", root)
 
 	// Store the workspace root for hierarchical ignore checking
@@ -116,7 +132,9 @@ func Start() error {
 	// Multiple calls with the same directories are safe (fsnotify deduplicates)
 	err := fsext.WalkDirectories(root, func(path string, d os.DirEntry, err error) error {
 		if err != nil {
-			return err
+			// Skip directories we don't have permission to access
+			slog.Debug("lsp watcher: Skipping directory due to error", "path", path, "error", err)
+			return nil
 		}
 
 		// Add directory to watcher (fsnotify handles deduplication automatically)
@@ -137,7 +155,8 @@ func Start() error {
 // fsnotify handles deduplication internally, so we don't need to track watched directories.
 func (gw *global) addDirectoryToWatcher(dirPath string) error {
 	if gw.watcher == nil {
-		return fmt.Errorf("lsp watcher: global watcher not initialized")
+		// File watching is disabled, skip silently
+		return nil
 	}
 
 	// Add directory to fsnotify watcher - fsnotify handles deduplication
@@ -160,7 +179,7 @@ func (gw *global) processEvents() {
 	cfg := config.Get()
 
 	if gw.watcher == nil || !gw.started.Load() {
-		slog.Error("lsp watcher: Global watcher not initialized")
+		slog.Debug("lsp watcher: Global watcher not available or not started")
 		return
 	}