denoland/deno · error
On Windows the target must be a file or directory
Error message
On Windows the target must be a file or directory
What it means
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).
Source
Thrown at ext/fs/std_fs.rs:1233
#[cfg(windows)]
fn symlink(
oldpath: &Path,
newpath: &Path,
file_type: Option<FsFileType>,
) -> FsResult<()> {
let file_type = match file_type {
Some(file_type) => file_type,
None => {
let old_meta = fs::metadata(oldpath);
match old_meta {
Ok(metadata) => {
if metadata.is_file() {
FsFileType::File
} else if metadata.is_dir() {
FsFileType::Directory
} else {
return Err(FsError::Io(io::Error::new(
io::ErrorKind::InvalidInput,
"On Windows the target must be a file or directory",
)));
}
}
Err(err) if err.kind() == io::ErrorKind::NotFound => {
return Err(FsError::Io(io::Error::new(
io::ErrorKind::InvalidInput,
"On Windows an `options` argument is required if the target does not exist",
)));
}
Err(err) => return Err(err.into()),
}
}
};
match file_type {
FsFileType::File => {View on GitHub (pinned to 9ad36f7a2c)
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
Example fix
// before
Deno.symlinkSync(target, link); // target is a named pipe on Windows
// after
Deno.symlinkSync(target, link, { type: 'file' }); Defensive patterns
Strategy: validation
Validate before calling
function symlinkSyncSafe(target: string, link: string): void {
let type: 'file' | 'dir' | undefined;
if (Deno.build.os === 'windows') {
const st = Deno.statSync(target); // follows link; throws if missing
type = st.isDirectory ? 'dir' : 'file';
if (!st.isFile && !st.isDirectory) {
throw new Error(`Cannot infer Windows link type for special file: ${target}`);
}
}
Deno.symlinkSync(target, link, type ? { type } : undefined);
} Type guard
function isPlainFsEntry(path: string): boolean {
try {
const st = Deno.statSync(path);
return st.isFile || st.isDirectory;
} catch {
return false;
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Windows dev boxes creating tool shims whose target is a pipe; provisioning scripts that mirror Unix /dev-style layouts.
Related errors
- On Windows an `options` argument is required if the target d
- ERR_FS_INVALID_SYMLINK_TYPE
- Source and destination paths refer to the same file
- the source path is not a valid file
- the source and destination are the same file
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/afa8a868b067a9ba.
Report an issue: GitHub.