Run Swift on Debian Trixie
Installing Swift on Debian is a no-brainer. Users can either pick up swiftly or unpack the current tarball, and if you are running a supported Debian version—e.g. Debian 12 Bookworm at the time of this writing—then you are good to go.
This article is about running the latest Swift version on the current stable Debian version: Trixie.
Symbolic links trick
When running swift repl on current Debian 13 Trixie, we end up with an error:
~/.local/share/swiftly/toolchains/6.2.4/usr/bin/lldb: error while loading shared libraries: libpython3.11.so.1.0: cannot open shared object file: No such file or directory
I have been dealing with this error for a while and, up to Swift 6.2.4, I would create symbolic links of the libpython files to sort of meet Swift REPL / LLDB requirements:
cd /usr/lib/$(uname -m)-linux-gnu
for f in libpython3.13.* ; do
ln -s $f $(echo $f | sed s/3\.13/3\.11/)
done
So much for a dependency!
It worked, until it didn’t
Then came Swift 6.3 with LLDB 21.0:
$ swift repl
PLEASE submit a bug report to and include the crash backtrace.
Stack dump:
0. Program arguments: ~/.local/share/swiftly/toolchains/6.3.0/usr/bin/lldb "--repl=-disable-objc-interop -color-diagnostics -Xcc -fcolor-diagnostics -empty-abi-descriptor -no-auto-bridging-header-chaining -in-process-plugin-server-path ~/.local/share/swiftly/toolchains/6.3.0/usr/lib/swift/host/libSwiftInProcPluginServer.so -plugin-path ~/.local/share/swiftly/toolchains/6.3.0/usr/lib/swift/host/plugins -plugin-path ~/.local/share/swiftly/toolchains/6.3.0/usr/local/lib/swift/host/plugins"
#0 0x00005565426d9928 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (~/.local/share/swiftly/toolchains/6.3.0/usr/bin/lldb+0x2e928)
#1 0x00005565426d76d5 llvm::sys::RunSignalHandlers() (~/.local/share/swiftly/toolchains/6.3.0/usr/bin/lldb+0x2c6d5)
#2 0x00005565426da9c1 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
#3 0x00007ff556a4bdf0 (/lib/x86_64-linux-gnu/libc.so.6+0x3fdf0)
#4 0x00007ff556aa3bce (/lib/x86_64-linux-gnu/libc.so.6+0x97bce)
#5 0x00007ff556aa3c29 __pthread_once (/lib/x86_64-linux-gnu/libc.so.6+0x97c29)
#6 0x00007ff5583d0b2c lldb_private::lldb_initialize_ScriptInterpreterPython() (~/.local/share/swiftly/toolchains/6.3.0/usr/bin/../lib/liblldb.so.21.0+0x11d0b2c)
#7 0x00007ff557b2b94d lldb_private::SystemInitializerFull::Initialize() (~/.local/share/swiftly/toolchains/6.3.0/usr/bin/../lib/liblldb.so.21.0+0x92b94d)
#8 0x00007ff557d702f9 lldb_private::SystemLifetimeManager::Initialize(std::unique_ptr<lldb_private::SystemInitializer, std::default_delete<lldb_private::SystemInitializer>>) (~/.local/share/swiftly/toolchains/6.3.0/usr/bin/../lib/liblldb.so.21.0+0xb702f9)
#9 0x00007ff557a3969f lldb::SBDebugger::InitializeWithErrorHandling() (~/.local/share/swiftly/toolchains/6.3.0/usr/bin/../lib/liblldb.so.21.0+0x83969f)
#10 0x00005565426bf54a main (~/.local/share/swiftly/toolchains/6.3.0/usr/bin/lldb+0x1454a)
#11 0x00007ff556a35ca8 (/lib/x86_64-linux-gnu/libc.so.6+0x29ca8)
#12 0x00007ff556a35d65 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29d65)
#13 0x00005565426bb041 _start (~/.local/share/swiftly/toolchains/6.3.0/usr/bin/lldb+0x10041)
💣 Program crashed: Bad pointer dereference at 0x0000000000000000
Platform: x86_64 Linux (Debian GNU/Linux 13 (trixie))
Thread 0 "lldb" crashed:
0 0x00007ff556b1a7b9 <unknown> in libc.so.6
...
Backtrace took 0.00s
The crash is happening in lldb_initialize_ScriptInterpreterPython(): LLDB (which backs the Swift REPL) is trying to load a Python scripting backend and crashing with a null pointer dereference, almost certainly because it was compiled against a specific libpython version that doesn’t exist on Trixie.
A Python C API symbol either moved or changed structure layout between 3.11 and 3.13—and unlike before, LLDB 21.0 is no longer forgiving about it.
I don’t know about you, but I gave up on submitting bugs to Apple. The most surgical fix is to replace the symbolic links with a stub library1 that exports all Python symbols LLDB needs as no-ops, instead of pointing at a real but ABI-mismatched Python 3.13.
First, we list the symbols liblldb.so.21.0 needs from Python:
nm -D ~/.local/share/swiftly/toolchains/6.3.0/usr/lib/liblldb.so.21.0 \
| awk '$1 == "U" {print $2}' \
| grep -E '^_?Py' \
| awk '{print "void " $1 "() {}"}' \
> /tmp/pystub.c
Then we build and install the stub:
gcc -shared -fPIC -o /tmp/lib.stub /tmp/pystub.c
sudo cp /tmp/lib.stub "/usr/lib/$(uname -m)-linux-gnu/libpython3.11.so.1.0"
A better approach
It sure is fun to hack all the things but it leaves LLDB without a functional Python runtime, and that matters. LLDB uses Python as its scripting engine: breakpoint callbacks, custom commands, and automation all run through it. Let’s do this properly.
The right path is to download the latest Python 3.11—and corresponding libnsl2 dependency—from Debian 12 Bookworm:
export ARCH=$(dpkg --print-architecture)
wget "http://ftp.debian.org/debian/pool/main/p/python3.11/libpython3.11_3.11.2-6+deb12u6_$ARCH.deb"
wget "http://ftp.debian.org/debian/pool/main/p/python3.11/libpython3.11-stdlib_3.11.2-6+deb12u6_$ARCH.deb"
wget "http://ftp.debian.org/debian/pool/main/p/python3.11/libpython3.11-minimal_3.11.2-6+deb12u6_$ARCH.deb"
wget "http://ftp.debian.org/debian/pool/main/libn/libnsl/libnsl2_1.3.0-2_$ARCH.deb"
Now let’s install them:
sudo dpkg -i libnsl2_1.3.0-2_*.deb
sudo dpkg -i libpython3.11-minimal*.deb libpython3.11-stdlib*.deb libpython3.11_*.deb
Just like Python, libnsl2 was also updated in Trixie:
$ apt-cache policy libnsl2
libnsl2:
Installed: 1.3.0-2
Candidate: 1.3.0-3+b3
Version table:
1.3.0-3+b3 500
500 http://deb.debian.org/debian trixie/main amd64 Packages
500 http://mirror.hetzner.com/debian/packages trixie/main amd64 Packages
*** 1.3.0-2 100
100 /var/lib/dpkg/status
Trixie has your back and offers to upgrade:
sudo apt update
sudo apt upgrade -y
And voilà 🍾
$ swift repl
Welcome to Swift version 6.3 (swift-6.3-RELEASE).
Type :help for assistance.
1> print("Hello, World!")
Hello, World!
2> import Foundation
3> print(ProcessInfo.processInfo.operatingSystemVersionString)
Debian GNU/Linux 13 (trixie)
Conclusion
Swift officially supports Debian stable. Except when it doesn’t. Debian 13 Trixie has been stable since June 2025, yet Swift 6.3 only targets Debian 12 Bookworm.
There’s no technical reason a modern compiled language runtime should be entangled with the system Python at all. LLDB’s Python scripting backend is a powerful debugging feature, not a hard runtime requirement for the Swift compiler itself. The fact that shipping for a new distro requires users to either fake a Python ABI or backport packages from the previous release says more about prioritization than complexity.
Hopefully Swift 6.4 gets there 🤞
-
A stub library is a shared library that exports the expected symbols but does nothing—it exists purely to satisfy the dynamic linker at load time. ↩︎