[BUG] claude update hangs indefinitely (100s+) when falling back from reflink to copy_file_range across filesystems, no timeout or progress indication

Status Fixed / completed
Reported on v2.1.217
Maintainer reply None cached
Activity 0 comments · opened Jul 22, 2026 · closed Jul 22, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Environment

OS: Linux, tested with Ubuntu and Arch.
Install type: native, custom launcher script (reads highest version-sorted entry under a versions directory, per the pattern described in the "Advanced setup" docs for replacing the managed launcher)
Filesystem layout:
$HOME (/home/chris) — NFS
$HOME/.cache — bind-mounted to local scratch storage (/scratch/local)
A separate NFS mount also in use for the actual installed versions directory (/work/chris/...)

What happened

claude update reported "Updating to 2.1.217..." and then hung indefinitely. Two separate runs hung for several minutes before being interrupted; a third run was captured under strace -f -o claude.strace claude update with a 120s timeout wrapper.

Root cause (from strace)

Download completes fast — the full update payload (~256 MB) arrives over HTTPS in about 2 seconds. Not a network issue.
The updater stages the downloaded file under $HOME/.cache/claude/staging/... (local filesystem in our case).
It attempts to install via reflink:
ioctl(19, BTRFS_IOC_CLONE or FICLONE, 16) = -1 EXDEV (Invalid cross-device link)

This fails because staging (.cache, local) and the destination (.local/share/claude/versions, NFS) are on different filesystems — expected and correctly detected.

  1. It falls back to a full copy:

13:36:37 copy_file_range(16, [0], 19, [0], 268573680, 0 <unfinished ...>
13:38:34 <... copy_file_range resumed>) = ? ← process killed by external timeout here, never returned

This single syscall never returns. It blocks for the entire remainder of the run (117+ seconds and counting when killed) with no timeout, no chunking/progress, and no way to tell from the CLI's output that this is what's stuck.

Why this matters

Falling back from reflink to copy_file_range on EXDEV is the right behavior — cross-filesystem $HOME/.cache vs $HOME/.local/share is a normal setup (common on HPC/academic clusters, and anywhere .cache is pointed at local/fast scratch storage on purpose). But the fallback path has no upper bound on how long it can block.
There is no user-visible indication that a large file copy is in progress, so a legitimately slow or temporarily stalled destination filesystem is indistinguishable from a hung/broken updater.
Interrupting the process mid-copy leaves partial state behind (e.g. a stale versions/<version> file from a previous attempt caused EEXIST on the next run, before the updater moved to a uniquely-suffixed temp filename — so this is at least partially handled, but the situation is still fragile).

Suggested fixes

Add a timeout (and/or periodic progress reporting) around the copy_file_range fallback path, with a clear error message if it's exceeded, rather than blocking silently.
Show visible progress during the install/copy phase distinct from the download phase, so users can tell which step is slow.
Consider allowing the final rename() to happen within whichever filesystem the staging directory is actually on (i.e., install location follows the writable/fast mount rather than always targeting $HOME/.local/share), when that's configurable or detectable.

Repro
Have $HOME/.cache and $HOME/.local/share on different filesystems where the latter is NFS with degraded/slow write throughput, and run claude update.

What Should Happen?

It should correctly copy the file

Error Messages/Logs

Steps to Reproduce

Have $HOME/.cache and $HOME/.local/share on different filesystems where the latter is NFS with degraded/slow write throughput, and run claude update.

Claude Model

Sonnet (default)

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.215 (I need previous because newer doesn't upgrade because it's newest)

Platform

Anthropic API

Operating System

Ubuntu/Debian Linux

Terminal/Shell

Xterm

Additional Information

_No response_

View original on GitHub ↗