{"record":{"id":"1944bdc4d5555f72","repo":"microsoft/typescript-go","slug":"fswatch-path-must-be-absolute","errorCode":null,"errorMessage":"fswatch: path must be absolute","messagePattern":"fswatch: path must be absolute","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/fswatch/watcher.go","lineNumber":25,"sourceCode":"\t\"path/filepath\"\n\t\"runtime\"\n\t\"slices\"\n\t\"strings\"\n\t\"sync\"\n\t\"syscall\"\n\n\t\"github.com/microsoft/typescript-go/internal/nativepath\"\n)\n\nvar errNilCallback = errors.New(\"fswatch: callback must not be nil\")\n\n// errRootPath is returned by WatchFile when the supplied path is a\n// filesystem root with no parent directory to watch.\nvar errRootPath = errors.New(\"fswatch: cannot watch a root path\")\n\n// errNotAbsolute is returned by [Watcher.WatchDirectory] and\n// [Watcher.WatchFile] when the supplied path is not absolute.\nvar errNotAbsolute = errors.New(\"fswatch: path must be absolute\")\n\n// ErrOverflow indicates that the kernel event queue overflowed and\n// some filesystem changes were missed. The watch remains\n// active; further events will continue to be delivered. Callers\n// should treat this as a signal to rescan the watched directory.\nvar ErrOverflow = errors.New(\"fswatch: event overflow; some changes were missed\")\n\n// ErrWatchTerminated indicates that the watch was terminated due to\n// an unrecoverable error (e.g. the watched directory was deleted or\n// the watch descriptor was revoked). No further events will be\n// delivered. Call Close to release remaining state.\nvar ErrWatchTerminated = errors.New(\"fswatch: watch terminated\")\n\n// ErrUnavailable indicates that a requested watcher is not\n// available on the current platform.\nvar ErrUnavailable = errors.New(\"fswatch: watcher not available on this platform\")\n\n// ErrFilesystemUnsupported indicates that the active watcher backend cannot","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/internal/fswatch/watcher.go#L7-L43","documentation":"Sentinel error returned by WatchDirectory and WatchFile when the cleaned path is not absolute. The API requires absolute paths because event delivery and internal bookkeeping key on them; filepath.Clean is applied first but never absolutizes, so relative inputs like \"src\" or \"./out\" are rejected. On Windows, IsAbs requires a drive-rooted (C:\\x) or UNC (\\\\server\\share\\x) form, so volume-relative paths like \"C:foo\" also fail.","triggerScenarios":"Passing a working-directory-relative path such as \"out\" or \"../src\". Passing a volume-relative path such as \"C:tmp\" on Windows. Building watch paths by joining user input onto an empty base.","commonSituations":"CLI tools forwarding user arguments straight to the watcher. Cross-platform code assuming Unix separators. Tests using relative fixture paths. Config files with '~' that was never expanded.","solutions":["Absolutize with filepath.Abs(dir) before subscribing","Derive watch paths from a rooted base directory constant","On Windows, normalize to drive-rooted or UNC form before the call"],"exampleFix":"// before\nwatch, err := fswatch.Default().WatchDirectory(\"out\", cb)\n\n// after\ndir, err := filepath.Abs(\"out\")\nif err != nil {\n    return err\n}\nwatch, err := fswatch.Default().WatchDirectory(dir, cb)","handlingStrategy":"validation","validationCode":"if !filepath.IsAbs(dir) {\n    abs, err := filepath.Abs(dir)\n    if err != nil {\n        return err\n    }\n    dir = abs\n}","typeGuard":null,"tryCatchPattern":"if _, err := w.WatchDirectory(dir, cb); err != nil {\n    if err.Error() == \"fswatch: path must be absolute\" {\n        dir, _ = filepath.Abs(dir)\n        // retry with the absolutized path\n    }\n}","preventionTips":["Absolutize every watch path once at configuration load","Derive watch paths from rooted constants, not raw user input","Expand ~ and environment variables before passing paths","On Windows, normalize to drive-rooted or UNC form"],"tags":["api-misuse","validation","paths","cross-platform"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}