{"record":{"id":"b730185d5d1cf240","repo":"microsoft/typescript-go","slug":"error-opening-directory-w","errorCode":null,"errorMessage":"error opening directory: %w","messagePattern":"error opening directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/fswatch/walkdir_windows.go","lineNumber":21,"sourceCode":"package fswatch\n\nimport (\n\t\"fmt\"\n\t\"syscall\"\n\t\"unsafe\"\n\n\t\"golang.org/x/sys/windows\"\n)\n\n// walkDir walks a directory tree on Windows using FindFirstFile/FindNextFile.\nfunc walkDir(dir string, recursive bool, fn func(path string, isDir bool) error) error {\n\trootPtr, err := windows.UTF16PtrFromString(dir)\n\tif err != nil {\n\t\treturn err\n\t}\n\tvar rootData windows.Win32FileAttributeData\n\tif err := windows.GetFileAttributesEx(rootPtr, windows.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&rootData))); err != nil {\n\t\treturn fmt.Errorf(\"error opening directory: %w\", err)\n\t}\n\tif rootData.FileAttributes&windows.FILE_ATTRIBUTE_DIRECTORY == 0 ||\n\t\trootData.FileAttributes&windows.FILE_ATTRIBUTE_REPARSE_POINT != 0 {\n\t\treturn syscall.ENOTDIR\n\t}\n\tif fn != nil {\n\t\tif err := fn(dir, true); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tstack := []string{dir}\n\tfor len(stack) > 0 {\n\t\tpath := stack[len(stack)-1]\n\t\tstack = stack[:len(stack)-1]\n\n\t\tspec := path + \"\\\\*\"\n\t\tspecPtr, err := windows.UTF16PtrFromString(spec)","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/internal/fswatch/walkdir_windows.go#L3-L39","documentation":"Returned by the Windows implementation of walkDir, the tree-enumeration helper used when watch setup must list a directory tree before arming OS watches. GetFileAttributesEx on the walk root failed, and the message wraps the Win32 error (ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND, ERROR_ACCESS_DENIED, and similar). The primary Windows watcher itself uses ReadDirectoryChangesW and does not walk, so this surfaces from walk-driven setup paths and tests that exercise the walker.","triggerScenarios":"walkDir runs against a directory that no longer exists, was deleted between the caller's existence check and the walk, sits on an unavailable network share, or denies attribute reads to the process. A path containing an embedded NUL fails earlier in UTF16PtrFromString and returns that error instead.","commonSituations":"Tree walks over UNC paths (\\\\server\\share) when the share drops mid-operation. Directories removed by a concurrent build step. Locked-down ACLs on system directories.","solutions":["Verify with os.Stat that the directory exists and is a directory immediately before the operation that walks it","Fix ACLs, or run under an account that can read directory attributes","Retry after the directory or share is available again","Keep the walked root stable for the duration of the walk; coordinate with cleanup jobs"],"exampleFix":"// before\nerr := walkDir(root, true, visit)\n\n// after\ninfo, err := os.Stat(root)\nif err != nil {\n    return err\n}\nif !info.IsDir() {\n    return fmt.Errorf(\"not a directory: %s\", root)\n}\nerr = walkDir(root, true, visit)","handlingStrategy":"validation","validationCode":"info, err := os.Stat(dir)\nif err != nil {\n    return err\n}\nif !info.IsDir() {\n    return syscall.ENOTDIR\n}","typeGuard":null,"tryCatchPattern":"err := walkDrivenSetup(dir)\nif err != nil {\n    if errors.Is(err, windows.ERROR_PATH_NOT_FOUND) || errors.Is(err, windows.ERROR_FILE_NOT_FOUND) {\n        // directory vanished: verify and retry\n    }\n    if errors.Is(err, windows.ERROR_ACCESS_DENIED) {\n        // fix ACLs or account\n    }\n}","preventionTips":["Validate existence and type right before any tree walk","Keep walked roots alive for the walk duration; coordinate with cleanup jobs","Run under accounts with read access to the target tree","Retry around transient share outages instead of failing permanently"],"tags":["windows","filesystem","walk","permissions","network-share"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}