# PyTorch install fails on Windows with WinError 206 — PythonSlicer.exe is not longPathAware

**URL:** <https://discourse.slicer.org/t/pytorch-install-fails-on-windows-with-winerror-206-pythonslicer-exe-is-not-longpathaware/47781>\
**Category:** Support\
**Created:** [July 31, 2026, 6:31pm UTC](https://discourse.slicer.org/t/pytorch-install-fails-on-windows-with-winerror-206-pythonslicer-exe-is-not-longpathaware/47781 "2026-07-31T18:31:45Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![pboarantes](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pboarantes/32/79408_2.png) [@pboarantes](https://discourse.slicer.org/u/pboarantes)\
**Post date:** [July 31, 2026, 6:31pm UTC](https://discourse.slicer.org/t/pytorch-install-fails-on-windows-with-winerror-206-pythonslicer-exe-is-not-longpathaware/47781/1 "2026-07-31T18:31:45Z")

</div>

**Environment**

- 3D Slicer 5.12.3, Windows 11
- Default install path: `C:\Users\<user>\AppData\Local\slicer.org\3D Slicer 5.12.3\`
- Extensions: TotalSegmentator, PyTorch, NNUNet
- torch 2.13.0+cu130 / torchvision 0.28.0+cu130 (selected automatically by light-the-torch)
- GPU: RTX 5070 Ti

**Disclosure up front:** I am a physician, not a software engineer. I worked through this with Claude (Anthropic) over a long debugging session. Every command below was run on my machine and the end state works, but please review critically rather than trusting it on my authority.

* * *

## Symptom

First run of TotalSegmentator → Apply. The PyTorch extension downloads the wheel and then dies:

```auto
Installing collected packages: torch, torchvision
ERROR: Could not install packages due to an OSError: [WinError 206] The filename or extension is too long:
'C:\Users\<user>\AppData\Local\slicer.org\3D Slicer 5.12.3\lib\Python\Lib\site-packages\torch-2.13.0+cu130.dist-info\licenses\third_party\kineto\libkineto\third_party\dynolog\third_party\prometheus-cpp\3rdparty\googletest\googlemock\scripts\generator'

```

followed by:

```auto
ModuleNotFoundError: No module named 'torchgen'

```

and, on the next attempt:

```auto
File ".../PyTorchUtils.py", line 162, in torchInstalled
    metadataPath = [p for p in importlib.metadata.files('torch') if 'METADATA' in str(p)][0]
TypeError: 'NoneType' object is not iterable

```

## Root cause

Three things combine, and none of them is user misconfiguration:

1. **The default install prefix is long.** `...\3D Slicer 5.12.3\lib\Python\Lib\site-packages\` is 86 characters on its own for a 5-character username. Longer usernames make it worse.
2. **Recent torch wheels ship a deeply nested third-party license tree.** Under `.dist-info/licenses/`, the upstream directory structure is preserved. The deepest branch reaches `licenses\third_party\kineto\libkineto\third_party\dynolog\third_party\prometheus-cpp\3rdparty\googletest\googlemock\scripts\generator\` — roughly 162 characters of suffix. Directory plus prefix is already ~248 characters; the files inside push it past the 260-character `MAX_PATH` limit. This is the part that changed: older torch wheels did not carry this tree, which is why the same install path worked in previous Slicer releases.
3. **Enabling long paths in the registry does not help.** Per Microsoft’s documentation, two conditions must both be met: the `LongPathsEnabled` registry value must be 1 **and** the application manifest must include the `longPathAware` element. pip runs as a subprocess of `PythonSlicer.exe`, which does not declare it. CPython’s own `python.exe` does, so this is specific to the Slicer launcher.

I set `LongPathsEnabled=1` and rebooted before understanding point 3, and the failure was byte-for-byte identical.

## Two secondary problems that make this hard to diagnose

**Retrying never recovers.** When pip dies partway through, it may already have written a valid `torch-2.13.0+cu130.dist-info` with METADATA. On the next run pip reports `Requirement already satisfied: torch>=2.1.2` and skips reinstallation, while `import torch` still fails. The site-packages tree has to be wiped manually before any retry.

**The error message is misleading.** A partial install leaves `site-packages\torch\` without ` __init__.py`. Python 3.3+ treats that as a namespace package and imports it successfully as an empty module, so instead of `ModuleNotFoundError` you get:

```auto
AttributeError: module 'torch' has no attribute ' __version__'

```

which looks like a version-detection bug rather than a broken install.

## Workaround

**Simplest, and what I would recommend to anyone hitting this:** reinstall Slicer to a short path such as `C:\Slicer5123\` instead of the default. That removes ~48 characters of prefix and the wheel installs normally with no further intervention.

**If you cannot reinstall,** the path below works but has a trap in it. In an **elevated** PowerShell, with Slicer closed:

powershell

```auto
$slicer = "$env:LOCALAPPDATA\slicer.org\3D Slicer 5.12.3"
$sp = "$slicer\lib\Python\Lib\site-packages"
$py = "$slicer\bin\PythonSlicer.exe"

# 1. remove any partial install from earlier attempts
Get-ChildItem $sp | Where-Object { $_.Name -match '^(torch|torchvision|torchaudio|torchgen|functorch)([-.]|$)' } |
  Remove-Item -Recurse -Force

# 2. short temp directory (pip unpacks there before copying)
New-Item -ItemType Directory C:\t -Force | Out-Null
$env:TMP = "C:\t"; $env:TEMP = "C:\t"

# 3. install into a short path
& $py -m pip install --target C:\sp --upgrade --no-deps `
  "torch==2.13.0+cu130" "torchvision==0.28.0+cu130" `
  --index-url https://download.pytorch.org/whl/cu130

# 4. move into site-packages (rename is a single FS operation, so MAX_PATH does not apply)
Get-ChildItem C:\sp -Directory | Where-Object { $_.Name -ne 'bin' } | ForEach-Object {
    $destino = Join-Path $sp $_.Name
    if (Test-Path $destino) { Remove-Item $destino -Recurse -Force }
    [System.IO.Directory]::Move($_.FullName, $destino)
}

# 5. REQUIRED: reset ACLs, or Slicer (unelevated) cannot read the files
icacls "$sp" /reset /T /C /Q

```

**Step 5 is not optional.** Files created under `C:\` by an elevated shell inherit the root ACL, and the move preserves it. Slicer then runs unelevated and gets `PermissionError: [WinError 5] Access is denied`. Worse, `os.path.exists()` swallows access errors and returns `False`, so the file appears to be missing when it is actually unreadable — I lost a fair amount of time on that. Reset the whole `site-packages` tree, not just the `torch*` directories: the torch wheel also installs `functorch`, and I initially missed it.

Verify in the Slicer Python console:

python

```auto
import torch, torchgen
print(torch. __version__ , torch.cuda.is_available(), torch.cuda.get_device_name(0))

```

Expected: `2.13.0+cu130 True NVIDIA GeForce RTX 5070 Ti`. After that, TotalSegmentator’s Apply proceeds normally.

## Suggested fixes

1. **Add `longPathAware` to the `PythonSlicer.exe` manifest at build time.** This is the structural fix and it removes the whole class of problem, not just torch:

xml

```auto
   <application xmlns="urn:schemas-microsoft-com:asm.v3">
     <windowsSettings>
       <longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
     </windowsSettings>
   </application>

```

1. **Make `PyTorchUtils.torchInstalled()` defensive.** It currently raises `TypeError` when `importlib.metadata.files('torch')` returns `None`, and `PermissionError` when a file in the RECORD is unreadable. Returning `False` on either would at least let the extension attempt a clean reinstall instead of dead-ending.
2. **Consider warning at install time** if the Slicer installation path is long enough that `site-packages` plus a typical deep wheel would exceed `MAX_PATH`.

Happy to test patches or provide any additional logs.

---

<div class="post-metadata">

**Author:** ![jamesobutler](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/jamesobutler/32/7511_2.png) [@jamesobutler](https://discourse.slicer.org/u/jamesobutler)\
**Post date:** [July 31, 2026, 7:40pm UTC](https://discourse.slicer.org/t/pytorch-install-fails-on-windows-with-winerror-206-pythonslicer-exe-is-not-longpathaware/47781/2 "2026-07-31T19:40:47Z")

</div>

Thanks for providing the details. Yes, it is something we are aware of in regards to PyTorch’s 2.13 release.

> <https://github.com/Slicer/Slicer/issues/6037#issuecomment-5023722563>
>
> Files that have longer path than \`MAX\_PATH\` (260 characters) cannot be accessed …in Slicer.
> 
> Such files can be created on any file system that supports longer paths, by using UNC path convention (i.e., adding the \`\\\\?\\UNC\\\` prefix to a path), because when a Win32 API function is called with an UNC path then Windows does not interpret the path (so path length limitations do not apply), but the name is forwarded it directly to the file system.
> 
> Long file paths can be also created by applications that have \`longPathAware\` element enabled in their manifest if "Win32 Long Paths" are enabled on the computer by editing the registry or group policies (see https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd).
> 
> \## Describe the solution you'd like
> 
> Slicer and all the libraries that it uses should stop relying on fixed path length (\`MAX\_PATH\` constant) on Windows and then in Slicer's application manifest \`longPathAware\` element could be set to enabled. This would allow Slicer to access (read/write/create/delete) files with long names on Windows.
> 
> \## Describe alternatives you've considered
> 
> Using UNC files at specific critical locations (where receiving long paths is more likely, for example in the DICOM importer) could alleviate some problems. However, this solution would only be partial and much more complex than using the proposed solution.
> 
> \## Additional context
> 
> https://discourse.slicer.org/t/slicerqr-development/15954/205

You may have installed torch using the Slicer PyTorch extension prior to yesterday’s integration of the following commit where we are temporarily trying to avoid installation of PyTorch 2.13 on Windows. If you upgrade your Slicer PyTorch extension (or uninstall and reinstall with a new download), it should enforce to avoid version 2.13.

> <https://github.com/fepegar/SlicerPyTorch/commit/74f8216f4841d84b8ceca3026aa18d022be78e78>
>
> torch 2.13 ships PEP 639 license files that reproduce PyTorch's vendored
> source …tree inside torch-\<version\>.dist-info/licenses. The deepest collected
> path is 162 characters relative to site-packages, while Windows limits
> directory creation to MAX\_PATH-12 (248 characters). Installation therefore
> fails with "\[WinError 206\] The filename or extension is too long" whenever the
> path of site-packages is longer than 86 characters, which a default Slicer
> installation is exactly at. The failed installation leaves a partially
> extracted torch package behind that is hard to remove, because deleting those
> files hits the same path length limit.
> 
> Exclude torch 2.13.\* on Windows, along with torchvision 0.28.\*, which requires
> torch 2.13 and would pull it back in. This can be reverted once PyTorch no
> longer collects the deeply nested license files.
> 
> See Slicer/light-the-torch#176 and pytorch/pytorch#185813.

PyTorch maintainers themselves are ultimately working on change that will drop some of the long paths that became an issue in their 2.13 release. See the following open work:

> <https://github.com/pytorch/pytorch/pull/185813>
>
> Fix for \[pytorch/pytorch#183434\](https://github.com/pytorch/pytorch/issues/18343…4).
> 
> The PEP 639 migration (#180237) replaced the old concatenated \`LICENSE\` blob with per-file \`license-files\` in \`pyproject.toml\`. The existing recursive globs:
> 
> \`\`\`toml
> license-files = \[
> "LICENSE",
> "third\_party/\*\*/LICENSE",
> "third\_party/\*\*/LICENSE.txt",
> "third\_party/\*\*/LICENSE.rst",
> "third\_party/\*\*/COPYING.BSD",
> \]
> \`\`\`
> 
> matched \*\*107 files\*\* in the source tree, but only \*\*~59\*\* represent code that actually ships in the wheel. The remainder are over-collection from nested submodule vendoring — tests, docs, bindings, build tools, and dynolog transitive deps.
> 
> This caused two concrete problems:
> 
> 1. \*\*Windows \`MAX\_PATH\` failures\*\* — PEP 639 copies each license into the wheel under \`.dist-info/licenses/\`, doubling path length. Deep dynolog paths (up to \*\*135 characters\*\* relative) exceeded Windows limits during packaging.
> 2. \*\*Incorrect license surface\*\* — including files like \`cpr/test/LICENSE\` (GPL-3.0) in the distribution metadata, even though that code is never compiled or linked into PyTorch.
> 
> \## How the explicit list was derived
> 
> The 59 paths in \`pyproject.toml\` were \*\*not\*\* picked manually one-by-one. They are the output of a repeatable audit that mirrors the issue author's "conservative exclusion" (which estimated ~61 paths on ~108 glob matches; this tree yields \*\*107 discovered → 59 shipped\*\*).
> 
> \### Step 1 — Start from the old glob universe
> 
> Run the same patterns PyTorch used before the audit:
> 
> \`\`\`toml
> LICENSE
> third\_party/\*\*/LICENSE
> third\_party/\*\*/LICENSE.txt
> third\_party/\*\*/LICENSE.rst
> third\_party/\*\*/COPYING.BSD
> \`\`\`
> 
> This finds every candidate license file the recursive globs would have collected (\*\*107 files\*\* in the current tree).
> 
> \### Step 2 — Apply exclusion rules
> 
> Each candidate is classified using structural rules in \`test/test\_license.py\`. Paths that match non-shipping trees — tests, docs, googletest, bindings, dynolog transitive deps, deep nested vendoring — are \*\*excluded\*\*.
> 
> \### Step 3 — Whatever survives = explicit list
> 
> The shipped set is computed directly from discovery minus exclusion:
> 
> \`\`\`python
> shipped = \[path for path in discovered if not is\_excluded(path)\]
> \# → 59 paths
> \`\`\`
> 
> Those 59 paths are what go into \`pyproject.toml\` \`license-files\`. The list is the \*\*output of the audit\*\*, not a separate manual pick.
> 
> \### Step 4 — Test locks it in
> 
> \`test\_pyproject\_license\_metadata\` asserts:
> 
> \`\`\`python
> project\["license-files"\] == shipped
> project\["license"\] == spdx\_from(shipped)
> \`\`\`
> 
> If a submodule is added or moved, the test fails until \`pyproject.toml\` and the exclusion rules are updated together.
> 
> 
> 
> cc @jeffdaily @sunway513 @jithunnair-amd @pruthvistony @ROCmSupport @jataylo @hongxiayang @naromero77amd @pragupta @jerrymannil @xinyazhang
