Per contrarian review on #614: - Reframe the LUKS-passphrase-equals-login-password line as an informed tradeoff (single compromise unlocks both, equivalent to eCryptfs's existing threat surface) rather than a setup tip. - Spell out the confidentiality posture vs eCryptfs explicitly so a privacy-conscious user evaluating the move doesn't downgrade silently. Note that pam_mount failure makes writes fail loudly (ENOENT through the symlink) rather than landing on plaintext. - Add a CLAUDE_CONFIG_DIR escape hatch — users who've reconfigured Claude Code's home dir can't blindly follow the ~/.claude symlink step; the constraint is the underlying NAME_MAX, not the path. - Add mountpoint and readlink verification commands alongside the existing getconf NAME_MAX check so the workaround surfaces its own success criteria. Co-Authored-By: Claude <claude@anthropic.com>
16 KiB
Troubleshooting
Built-in Diagnostics
Run the --doctor flag to check your system for common issues:
# Deb install
claude-desktop --doctor
# AppImage
./claude-desktop-*.AppImage --doctor
This runs a series of checks and prints pass/fail results with suggested fixes:
| Check | What it verifies |
|---|---|
| Installed version | Package version via dpkg |
| Display server | Wayland/X11 detection and mode |
| Input method | IBus/GTK immodule sanity (ibus-gtk3 installed, cache fresh, XWayland routing note) |
| Electron binary | Existence and version |
| Chrome sandbox | Correct permissions (4755/root) |
| SingletonLock | Stale lock file detection |
| MCP config | JSON validity and server count |
| Node.js | Version (v20+ recommended for MCP) |
| Desktop entry | .desktop file presence |
| Disk space | Free space on config partition |
| Log file | Log file size |
Example output:
Claude Desktop Diagnostics
================================
[PASS] Installed version: 1.1.4498-1.3.15
[PASS] Display server: Wayland (WAYLAND_DISPLAY=wayland-0)
[PASS] Electron: found at /usr/lib/claude-desktop/node_modules/electron/dist/electron
[PASS] Chrome sandbox: permissions OK
[PASS] SingletonLock: no lock file (OK)
[PASS] MCP config: valid JSON
[PASS] Node.js: v22.14.0
[PASS] Desktop entry: /usr/share/applications/claude-desktop.desktop
[PASS] Disk space: 632284MB free
[PASS] Log file: 1352KB
All checks passed.
When opening an issue, include the output of --doctor to help with diagnosis.
Application Logs
Runtime logs are available at:
~/.cache/claude-desktop-debian/launcher.log
Common Issues
Window Scaling Issues
If the window doesn't scale correctly on first launch:
- Right-click the Claude Desktop tray icon
- Select "Quit" (do not force quit)
- Restart the application
This allows the application to save display settings properly.
Global Hotkey Not Working (Wayland)
If the global hotkey (Ctrl+Alt+Space) doesn't work, ensure you're not running in native Wayland mode:
- Check your logs at
~/.cache/claude-desktop-debian/launcher.log - Look for "Using X11 backend via XWayland" - this means hotkeys should work
- If you see "Using native Wayland backend", unset
CLAUDE_USE_WAYLANDor ensure it's not set to1
Note: Native Wayland mode doesn't support global hotkeys due to Electron/Chromium limitations with XDG GlobalShortcuts Portal.
See CONFIGURATION.md for more details on the CLAUDE_USE_WAYLAND environment variable.
Keyboard Input Doesn't Work (IBus / GTK Input Method)
If typing into the chat does nothing, characters get swallowed, or
dead-key sequences (e.g. `e → è) don't compose, your GTK
input module integration with the Electron-bundled GTK is broken.
Common symptoms:
- No characters appear when typing into any text field
- The first keystroke after focus is dropped, subsequent ones work
- CJK input methods (IBus, Fcitx) not engaging
- Compose key / dead-key sequences silently drop
First step: run claude-desktop --doctor. It checks for the
common misconfigurations and prints fix commands inline:
ibus-gtk3package missing whileGTK_IM_MODULE=ibus- GTK immodules cache stale (the active module isn't listed by
gtk-query-immodules-3.0) - XWayland session routing IBus through XIM (lossy for some IMEs —
set
CLAUDE_USE_WAYLAND=1to use native Wayland IME) - Active value of
CLAUDE_GTK_IM_MODULEif you've set the override
If --doctor is clean but input still misbehaves, switch the
launcher to a different GTK input module. Set CLAUDE_GTK_IM_MODULE
and Claude Desktop will propagate it as GTK_IM_MODULE to Electron
at startup:
# Bypass IBus entirely — uses the X Input Method (XIM) protocol
CLAUDE_GTK_IM_MODULE=xim claude-desktop
# To make it persistent, export it from your shell profile:
# echo 'export CLAUDE_GTK_IM_MODULE=xim' >> ~/.profile
Valid values: anything your GTK installation supports (xim, ibus,
fcitx, simple, etc.). When the override is active, the launcher
logs a line to ~/.cache/claude-desktop-debian/launcher.log:
GTK_IM_MODULE override: ibus -> xim (via CLAUDE_GTK_IM_MODULE)
Trade-off: xim is the lowest-common-denominator input module
and does not support advanced IME features like CJK candidate
windows or rich compose-key sequences. Only reach for it if your
real input method (IBus/Fcitx) is broken; if you depend on CJK or
compose, prefer fixing the IBus/Fcitx integration instead.
AppImage Sandbox Warning
AppImages run with --no-sandbox due to electron's chrome-sandbox requiring root privileges for unprivileged namespace creation. This is a known limitation of AppImage format with Electron applications.
For enhanced security, consider:
- Using the .deb package instead
- Running the AppImage within a separate sandbox (e.g., bubblewrap)
- Using Gear Lever's integrated AppImage management for better isolation
Cowork on Ubuntu 24.04+ (AppArmor Blocks User Namespaces)
Ubuntu 24.04 ships with apparmor_restrict_unprivileged_userns=1
by default, which blocks the unprivileged user namespaces that
Cowork's bubblewrap sandbox relies on. Symptoms:
claude-desktop --doctorreportsbubblewrap: sandbox probe failedwithOperation not permittedin stderr.~/.config/Claude/logs/cowork_vm_daemon.logcontainsbwrap is installed but cannot create a user namespace.- Cowork sessions hang at "Starting VM..." or loop on reconnect.
Permit user namespaces for bwrap via an AppArmor profile (one-time
setup, requires sudo):
sudo tee /etc/apparmor.d/bwrap <<'EOF'
abi <abi/4.0>,
include <tunables/global>
profile bwrap /usr/bin/bwrap flags=(unconfined) {
userns,
include if exists <local/bwrap>
}
EOF
sudo apparmor_parser -r /etc/apparmor.d/bwrap
After applying the profile, run claude-desktop --doctor — the
bubblewrap probe should pass, and Cowork should start without
falling back to host-direct.
Security note: this grants /usr/bin/bwrap the unconfined
profile plus the userns capability. It matches the behavior
bwrap had on Ubuntu 22.04 and earlier, and on most other distros,
but is a system-wide change that affects every program invoking
/usr/bin/bwrap (not just Claude Desktop). Review the profile
against your threat model before applying.
Credit: this workaround was contributed by @hfyeh in #351.
Cowork: "VM connection timeout after 60 seconds"
If Cowork fails with a VM timeout, the KVM backend is selected but the guest VM cannot connect back to the host via vsock within the timeout window. Common causes:
- First-boot initialization — the guest VM may take longer than 60 seconds on first launch
- vsock driver issues — the host may be missing the
vhost_vsockmodule (sudo modprobe vhost_vsock), or the guest initrd may lackvmw_vsock_virtio_transport
Fix: Force the bubblewrap backend, which provides namespace-level isolation without a VM:
COWORK_VM_BACKEND=bwrap claude-desktop
See CONFIGURATION.md for how to make this permanent.
Cowork: virtiofsd not found (Fedora/RHEL)
On Fedora and RHEL, virtiofsd installs to /usr/libexec/virtiofsd which is
outside $PATH. The --doctor check detects it there automatically and will
show [PASS], but the KVM backend spawns virtiofsd by name at runtime and
resolves it through $PATH only.
Fix: Create a symlink so the KVM backend can find it at runtime:
sudo ln -s /usr/libexec/virtiofsd /usr/local/bin/virtiofsd
On Debian/Ubuntu, the same issue can occur with /usr/lib/qemu/virtiofsd.
Cowork: cross-device link error on Fedora tmpfs /tmp
On Fedora, /tmp is a tmpfs by default. VM bundle downloads may fail with EXDEV: cross-device link not permitted when moving files from /tmp to ~/.config/Claude/.
Fix: Set TMPDIR to a directory on the same filesystem:
mkdir -p ~/.config/Claude/tmp
TMPDIR=~/.config/Claude/tmp claude-desktop
Or add TMPDIR=%h/.config/Claude/tmp to the Exec= line in your .desktop file.
Cowork: ENAMETOOLONG on encrypted home (eCryptfs)
Cowork sessions can fail with an opaque ENAMETOOLONG error when
$HOME is on a filesystem with a short filename limit. The common
case is eCryptfs — the legacy "encrypted home" option on older
Ubuntu and Linux Mint installs, which caps individual filenames at
143 chars because of filename-encryption overhead. Standard
filesystems (ext4, btrfs, xfs, zfs) cap at 255 chars and are fine.
Why it happens: Claude Code creates one directory per session
under ~/.claude/projects/, named after the sanitized host CWD. For
cowork sessions the host CWD is the deeply nested outputs dir under
~/.config/Claude/local-agent-mode-sessions/<accountId>/<orgId>/local_<uuid>/outputs,
which sanitizes to ~180 chars — fits ext4 but exceeds the eCryptfs
143-char ceiling.
Diagnosis: claude-desktop --doctor detects this automatically
and emits a [WARN] Filename limit: NAME_MAX=143… line, plus an
eCryptfs-specific hint when the filesystem type matches. You can
also check by hand:
df -T $HOME # look for type "ecryptfs"
getconf NAME_MAX $HOME # eCryptfs reports 143; ext4 reports 255
Workaround: move Claude's data onto a separate LUKS-encrypted
ext4 volume (NAME_MAX = 255) and symlink the original paths back.
~/.claude/ is the critical one — that's where Claude Code creates
the long-named per-session dirs that overflow the limit — and
~/.config/Claude/ plus ~/.cache/claude-desktop-debian/ are
relocated alongside it so all Claude state lives on the same volume.
This keeps the data encrypted at rest while sidestepping the
eCryptfs filename-length cap.
# 1. Create a 2 GB LUKS container
sudo dd if=/dev/urandom of=/opt/claude-secure.img bs=1M count=2048 \
status=progress
sudo cryptsetup luksFormat /opt/claude-secure.img
sudo cryptsetup open /opt/claude-secure.img claude-secure
sudo mkfs.ext4 /dev/mapper/claude-secure
# 2. Mount and move Claude's data in
sudo mkdir -p /mnt/claude-secure
sudo mount /dev/mapper/claude-secure /mnt/claude-secure
sudo chown "$USER:$USER" /mnt/claude-secure
mv ~/.config/Claude /mnt/claude-secure/Claude-config
mv ~/.cache/claude-desktop-debian /mnt/claude-secure/claude-cache
# ~/.claude may not exist yet on a fresh install — create the target
# either way so the symlink below resolves.
if [ -e ~/.claude ]; then
mv ~/.claude /mnt/claude-secure/claude-home
else
mkdir -p /mnt/claude-secure/claude-home
fi
ln -s /mnt/claude-secure/Claude-config ~/.config/Claude
ln -s /mnt/claude-secure/claude-cache ~/.cache/claude-desktop-debian
ln -s /mnt/claude-secure/claude-home ~/.claude
# 3. Verify the filename limit and the symlinks
getconf NAME_MAX /mnt/claude-secure # should print 255
mountpoint /mnt/claude-secure # confirms the volume is mounted
readlink ~/.claude # /mnt/claude-secure/claude-home
readlink ~/.config/Claude # /mnt/claude-secure/Claude-config
If you've set CLAUDE_CONFIG_DIR (or otherwise reconfigured
Claude Code to use a directory other than ~/.claude/), the
~/.claude symlink above doesn't apply — adapt the path to wherever
your Claude Code config actually lives. The constraint is the same:
the directory tree where Claude Code creates per-session project
dirs must sit on a filesystem with NAME_MAX ≥ ~200.
Auto-mount at login with pam_mount so the volume unlocks
without a manual cryptsetup open:
sudo apt install libpam-mount
Add a <volume> entry to /etc/security/pam_mount.conf.xml
(replace YOUR_USERNAME with your login name):
<volume user="YOUR_USERNAME" fstype="crypt"
path="/opt/claude-secure.img"
mountpoint="/mnt/claude-secure"
options="" />
libpam-mount registers itself with /etc/pam.d/common-auth and
/etc/pam.d/common-session automatically on install.
Notes:
- Tested on Linux Mint with LightDM as the display manager.
- LUKS passphrase tradeoff: for
pam_mountto unlock silently at login the LUKS passphrase must match your login password. That means one compromise unlocks both your session and the encrypted volume — equivalent to the threat surface eCryptfs already had, but worth a deliberate choice. Use a distinct LUKS passphrase if you'd rather be prompted on each unlock. - Confidentiality posture vs eCryptfs. The LUKS image lives at
/opt/claude-secure.img, outside$HOMEand outside whatever encryption envelope eCryptfs gives you. Ifpam_mountever fails silently — wrong passphrase, mount race at login, profile error — Claude won't start (the symlink targets won't exist), so writes fail loudly rather than landing on plaintext disk. Verify withmountpoint /mnt/claude-secureafter login if you're unsure. - 2 GB is a conservative starting size; the Claude config directory can exceed 500 MB once cowork session history accumulates. Resize if needed.
- This is a system-wide change that affects login flow — review the pam_mount config against your threat model before applying.
Credit: reported with detailed --doctor output by
@michelsfun; LUKS-volume workaround
contributed by @proffalken in
#590.
Authentication Errors (401)
If you encounter recurring "API Error: 401" messages after periods of inactivity, the cached OAuth token may need to be cleared. This is an upstream application issue reported in #156.
To fix manually (credit: MrEdwards007):
- Close Claude Desktop completely
- Edit
~/.config/Claude/config.json - Remove the line containing
"oauth:tokenCache"(and any trailing comma if needed) - Save the file and restart Claude Desktop
- Log in again when prompted
A scripted solution is also available at the bottom of this comment.
Uninstallation
For APT repository installations (Debian/Ubuntu)
# Remove package
sudo apt remove claude-desktop
# Remove the repository and GPG key
sudo rm /etc/apt/sources.list.d/claude-desktop.list
sudo rm /usr/share/keyrings/claude-desktop.gpg
For DNF repository installations (Fedora/RHEL)
# Remove package
sudo dnf remove claude-desktop
# Remove the repository
sudo rm /etc/yum.repos.d/claude-desktop.repo
For AUR installations (Arch Linux)
# Using yay
yay -R claude-desktop-appimage
# Or using paru
paru -R claude-desktop-appimage
# Or using pacman directly
sudo pacman -R claude-desktop-appimage
For .deb packages (manual install)
# Remove package
sudo apt remove claude-desktop
# Or: sudo dpkg -r claude-desktop
# Remove package and configuration
sudo dpkg -P claude-desktop
For .rpm packages
# Remove package
sudo dnf remove claude-desktop
# Or: sudo rpm -e claude-desktop
For AppImages
- Delete the
.AppImagefile - Remove the
.desktopfile from~/.local/share/applications/ - If using Gear Lever, use its uninstall option
Remove user configuration (all formats)
rm -rf ~/.config/Claude