{"record":{"id":"afa8a868b067a9ba","repo":"denoland/deno","slug":"on-windows-the-target-must-be-a-file-or-directory","errorCode":null,"errorMessage":"On Windows the target must be a file or directory","messagePattern":"On Windows the target must be a file or directory","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ext/fs/std_fs.rs","lineNumber":1233,"sourceCode":"\n#[cfg(windows)]\nfn symlink(\n  oldpath: &Path,\n  newpath: &Path,\n  file_type: Option<FsFileType>,\n) -> FsResult<()> {\n  let file_type = match file_type {\n    Some(file_type) => file_type,\n    None => {\n      let old_meta = fs::metadata(oldpath);\n      match old_meta {\n        Ok(metadata) => {\n          if metadata.is_file() {\n            FsFileType::File\n          } else if metadata.is_dir() {\n            FsFileType::Directory\n          } else {\n            return Err(FsError::Io(io::Error::new(\n              io::ErrorKind::InvalidInput,\n              \"On Windows the target must be a file or directory\",\n            )));\n          }\n        }\n        Err(err) if err.kind() == io::ErrorKind::NotFound => {\n          return Err(FsError::Io(io::Error::new(\n            io::ErrorKind::InvalidInput,\n            \"On Windows an `options` argument is required if the target does not exist\",\n          )));\n        }\n        Err(err) => return Err(err.into()),\n      }\n    }\n  };\n\n  match file_type {\n    FsFileType::File => {","sourceCodeStart":1215,"sourceCodeEnd":1251,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/fs/std_fs.rs#L1215-L1251","documentation":"On Windows, Deno.symlink()/symlinkSync() must know whether to create a file or directory symlink because the OS APIs differ. When options omits the type, Deno stats oldpath to infer it; if the metadata exists but is neither a regular file nor a directory (named pipe, device, etc.), the call fails with io::ErrorKind::InvalidInput 'On Windows the target must be a file or directory' (ext/fs/std_fs.rs:1233).","triggerScenarios":"Deno.symlinkSync(target, link) on Windows where target exists but is a named pipe or other special file; scripts ported from Unix that freely symlink special files.","commonSituations":"Windows dev boxes creating tool shims whose target is a pipe; provisioning scripts that mirror Unix /dev-style layouts.","solutions":["Pass the type explicitly: Deno.symlinkSync(target, link, { type: 'file' }) (or 'dir')","Rely on inference only when the target is a plain file or directory","Branch on Deno.build.os and skip symlinking special files on Windows"],"exampleFix":"// before\nDeno.symlinkSync(target, link); // target is a named pipe on Windows\n\n// after\nDeno.symlinkSync(target, link, { type: 'file' });","handlingStrategy":"validation","validationCode":"function symlinkSyncSafe(target: string, link: string): void {\n  let type: 'file' | 'dir' | undefined;\n  if (Deno.build.os === 'windows') {\n    const st = Deno.statSync(target); // follows link; throws if missing\n    type = st.isDirectory ? 'dir' : 'file';\n    if (!st.isFile && !st.isDirectory) {\n      throw new Error(`Cannot infer Windows link type for special file: ${target}`);\n    }\n  }\n  Deno.symlinkSync(target, link, type ? { type } : undefined);\n}","typeGuard":"function isPlainFsEntry(path: string): boolean {\n  try {\n    const st = Deno.statSync(path);\n    return st.isFile || st.isDirectory;\n  } catch {\n    return false;\n  }\n}","tryCatchPattern":null,"preventionTips":["Always pass { type: 'file' | 'dir' } on Windows instead of relying on inference","Only let Deno infer the type when the target is a plain file or directory","Skip symlinking named pipes and device files on Windows entirely"],"tags":["filesystem","symlink","windows","invalid-input","deno"],"backgroundTag":"windows-symlink-type","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}