denoland/deno · error
On Windows an `options` argument is required if the target d
Error message
On Windows an `options` argument is required if the target does not exist
What it means
On Windows, when Deno.symlink()/symlinkSync() is called without options, Deno stats oldpath to infer the link type; if fs::metadata returns NotFound (the target does not exist), inference is impossible and the call fails with io::ErrorKind::InvalidInput 'On Windows an `options` argument is required if the target does not exist' (ext/fs/std_fs.rs:1240). Unix allows dangling symlinks, so this is Windows-specific.
Source
Thrown at ext/fs/std_fs.rs:1240
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 => {
std::os::windows::fs::symlink_file(oldpath, newpath)?;
}
FsFileType::Directory => {
std::os::windows::fs::symlink_dir(oldpath, newpath)?;
}
FsFileType::Junction => {
junction::create(oldpath, newpath)?;View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Create the target first, then the symlink
- Always pass { type: 'file' } or { type: 'dir' } on Windows when the target may be absent
- Gate dangling-link behavior on Deno.build.os !== 'windows'
Example fix
// before
Deno.symlinkSync('./config.toml', 'link.toml'); // config.toml missing, Windows
// after
Deno.symlinkSync('./config.toml', 'link.toml', { type: 'file' }); Defensive patterns
Strategy: validation
Validate before calling
function ensureSymlinkable(target: string, link: string): void {
const onWindows = Deno.build.os === 'windows';
let type: 'file' | 'dir' | undefined;
if (onWindows) {
try {
type = Deno.statSync(target).isDirectory ? 'dir' : 'file';
} catch {
type = undefined; // target missing: caller must decide the link type
}
}
if (onWindows && !type) {
throw new Error(
`Windows cannot infer link type; pass { type } or create the target first: ${target}`,
);
}
Deno.symlinkSync(target, link, type ? { type } : undefined);
} Type guard
async function targetExists(target: string): Promise<boolean> {
try {
await Deno.stat(target);
return true;
} catch {
return false;
}
} Prevention
- Create the target file/directory before symlinking it on Windows
- Pass { type: 'file' } or { type: 'dir' } explicitly in cross-platform code
- Do not port Unix dangling-symlink patterns to Windows
When it happens
Trigger: Deno.symlinkSync('./config.toml', 'link.toml') before ./config.toml exists; installers pre-creating links to paths a later setup step will materialize; any code relying on dangling symlinks on Windows.
Common situations: Cross-platform scripts developed on macOS/Linux (dangling links fine) breaking on Windows; dotfile managers creating links before stowing files.
Related errors
- On Windows the target must be a file or directory
- ERR_FS_INVALID_SYMLINK_TYPE
- Path has no root.
- refusing to materialize package into symlinked directory
- {}, symlink '{}' -> '{}'
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/d12d186a09ae0bdf.
Report an issue: GitHub.