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:
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:
ModuleNotFoundError: No module named 'torchgen'
and, on the next attempt:
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:
- 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. - Recent torch wheels ship a deeply nested third-party license tree. Under
.dist-info/licenses/, the upstream directory structure is preserved. The deepest branch reacheslicenses\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-characterMAX_PATHlimit. 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. - Enabling long paths in the registry does not help. Per Microsoft’s documentation, two conditions must both be met: the
LongPathsEnabledregistry value must be 1 and the application manifest must include thelongPathAwareelement. pip runs as a subprocess ofPythonSlicer.exe, which does not declare it. CPython’s ownpython.exedoes, 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:
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
$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
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
- Add
longPathAwareto thePythonSlicer.exemanifest at build time. This is the structural fix and it removes the whole class of problem, not just torch:
xml
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>
- Make
PyTorchUtils.torchInstalled()defensive. It currently raisesTypeErrorwhenimportlib.metadata.files('torch')returnsNone, andPermissionErrorwhen a file in the RECORD is unreadable. ReturningFalseon either would at least let the extension attempt a clean reinstall instead of dead-ending. - Consider warning at install time if the Slicer installation path is long enough that
site-packagesplus a typical deep wheel would exceedMAX_PATH.
Happy to test patches or provide any additional logs.