Description
Due to upstream Go issue golang/go#39786, any time Terraform uses filepath.EvalSymlinks
it will fail on Windows systems where the given symlink refers to a UNC-style path to a volume, and where that volume doesn't have a DOS drive letter associated to it.
UNC-style raw paths are those starting with \\?\
, which bypass the Win32 layer's attempts to apply DOS-style path mapping (via a mapping table of drive letters in the object store) and instead just pass the string directly to the kernel.
The Go standard library seems to assume that it's always possible to unpack such a path into an equivalent DOS-style path, but that isn't true: \\?\
paths can be used to refer to items that are not addressable by DOS-style paths, either due to syntax constraints (filenames containing characters that are reserved under DOS) or due to the target object not being included in the DOS devices mapping table at all.
On modern Windows, particularly in contexts involving virtualization, it's common to make a volume appear as if it is a subdirectory of another "drive" (in the DOS sense), rather than assigning it a drive letter directly, either to give that volume a more symbolic path name or to support scenarios where the system needs to interact with more than 26 distinct volumes and thus can't assign all of them a unique drive letter. Users achieve that by creating a symlink to a UNC-style raw volume path, such as the \?\Volume{1b3b1146-4076-11e1-84aa-806e6f6e6963}\
example shown in the upstream Go issue.
All of this comes together to mean that Terraform users can run into a number of strange errors when trying to use Terraform in directories that the user has accessed via a symlink to a UNC-style raw path, because the Go standard library fails with an error if Terraform calls filepath.EvalSymlinks
(directly or indirectly) on such a path.
Terraform uses symlinks itself in a few spots, including:
- Avoiding making copies of plugin package directories in the global plugin cache directory, by symlinking from
.terraform/...
to there. - Attempting to optimize against repeated downloads of the same remote module source address, by symlinking subsequent references to the directory created in response to the first reference.
Terraform also sometimes uses filepath.EvalSymlinks
against symlinks it wasn't responsible for creating, which would presumably exhibit the same problems.
The Go team still seems to be working on understanding the root of this problem over in golang/go#39786, so for the moment this issue is here just to track that upstream blocker. We don't have enough context at our end to know the root cause here, and so we're monitoring the upstream issue to see where that leads before we take any actions on our end.