{"id":"d9b5033c73ed34d3","repo":"gohugoio/hugo","slug":"errnosuchwatch","errorCode":"errNoSuchWatch","errorMessage":"watch does not exist","messagePattern":"watch does not exist","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"watcher/filenotify/poller.go","lineNumber":19,"sourceCode":"package filenotify\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/fsnotify/fsnotify\"\n\t\"github.com/gohugoio/hugo/common/herrors\"\n)\n\nvar (\n\t// errPollerClosed is returned when the poller is closed\n\terrPollerClosed = errors.New(\"poller is closed\")\n\t// errNoSuchWatch is returned when trying to remove a watch that doesn't exist\n\terrNoSuchWatch = errors.New(\"watch does not exist\")\n)\n\n// filePoller is used to poll files for changes, especially in cases where fsnotify\n// can't be run (e.g. when inotify handles are exhausted)\n// filePoller satisfies the FileWatcher interface\ntype filePoller struct {\n\t// the duration between polls.\n\tinterval time.Duration\n\t// watches is the list of files currently being polled, close the associated channel to stop the watch\n\twatches map[string]struct{}\n\t// Will be closed when done.\n\tdone chan struct{}\n\t// events is the channel to listen to for watch events\n\tevents chan fsnotify.Event\n\t// errors is the channel to listen to for watch errors\n\terrors chan error\n\t// mu locks the poller for modification\n\tmu sync.Mutex","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/watcher/filenotify/poller.go#L1-L37","documentation":"errNoSuchWatch (watcher/filenotify/poller.go:19) is returned by the polling file watcher's Remove(name) when the given path isn't in its watches map. It indicates an attempt to unwatch a file/directory that was never added or was already removed, keeping Remove's contract symmetric with fsnotify's behavior.","triggerScenarios":"filePoller.Remove(name) called for a path absent from w.watches — e.g. Hugo's server removing a watch for a deleted/renamed directory that was already unwatched, or double-removal during watcher reconfiguration.","commonSituations":"Rapid delete/rename churn of content or asset directories while `hugo server` runs in polling mode (--poll, network mounts, exhausted inotify); module/mount config changes that rebuild the watch set and remove paths twice.","solutions":["Generally harmless — Hugo tolerates it during watch-set updates; ignore one-off occurrences.","Restart `hugo server` if watching becomes inconsistent after heavy file churn.","Avoid polling mode where possible (fix inotify limits instead of --poll) to reduce watch-set races."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"// track what you've added\nif !watched[path] { return } // nothing to remove","typeGuard":"func isNoSuchWatch(err error) bool { return err != nil && err.Error() == \"watch does not exist\" }","tryCatchPattern":"if err := w.Remove(path); err != nil {\n    if isNoSuchWatch(err) { /* already removed — idempotent, ignore */ } else { return err }\n}","preventionTips":["Keep a set of currently-watched paths and only Remove ones you added","Treat Remove of a missing watch as idempotent no-op rather than a failure","Avoid double-remove races by serializing add/remove on the watcher through one goroutine"],"tags":["hugo","file-watcher","polling","hugo-server"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}