@@ -813,6 +813,15 @@ func (s *VectorStore) addPathToWatcher(ctx context.Context, path string) error {
813813}
814814
815815func (s * VectorStore ) watchLoop (ctx context.Context , docPaths []string ) {
816+ // Capture watcher reference at goroutine start to avoid racing with Close()
817+ // which sets s.watcher = nil under watcherMu.
818+ s .watcherMu .Lock ()
819+ watcher := s .watcher
820+ s .watcherMu .Unlock ()
821+ if watcher == nil {
822+ return
823+ }
824+
816825 var debounceTimer * time.Timer
817826 debounceDuration := 2 * time .Second
818827 pendingChanges := make (map [string ]bool )
@@ -929,7 +938,7 @@ func (s *VectorStore) watchLoop(ctx context.Context, docPaths []string) {
929938 slog .Info ("File watcher stopped" , "strategy" , s .name )
930939 return
931940
932- case event , ok := <- s . watcher .Events :
941+ case event , ok := <- watcher .Events :
933942 if ! ok {
934943 return
935944 }
@@ -940,8 +949,10 @@ func (s *VectorStore) watchLoop(ctx context.Context, docPaths []string) {
940949
941950 if event .Op & fsnotify .Create != 0 {
942951 s .watcherMu .Lock ()
943- if err := s .addPathToWatcher (ctx , event .Name ); err != nil {
944- slog .Debug ("Could not watch new path" , "path" , event .Name , "error" , err )
952+ if s .watcher != nil {
953+ if err := s .addPathToWatcher (ctx , event .Name ); err != nil {
954+ slog .Debug ("Could not watch new path" , "path" , event .Name , "error" , err )
955+ }
945956 }
946957 s .watcherMu .Unlock ()
947958 }
@@ -974,7 +985,7 @@ func (s *VectorStore) watchLoop(ctx context.Context, docPaths []string) {
974985 }
975986 debounceTimer = time .AfterFunc (debounceDuration , processChanges )
976987
977- case err , ok := <- s . watcher .Errors :
988+ case err , ok := <- watcher .Errors :
978989 if ! ok {
979990 return
980991 }
0 commit comments