[BUG] Bug: File edits cause metadata loss (group, setuid, xattrs, hardlinks)

Resolved 💬 4 comments Opened May 20, 2026 by monperrus Closed Jun 19, 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?

Claude Code's Edit and Write tools replace files via delete+create rather than in-place modification. The inode always changes after an edit. While basic rwx permission bits are recovered, several important pieces of file metadata are silently lost: group ownership, setuid/setgid/sticky bits, extended attributes, and hardlinks.

What Should Happen?

File edits should preserve all metadata. The standard approach is an atomic write-to-tempfile + rename(tmpfile, path), followed by copying metadata from the original:

  • fchown to restore uid + gid
  • fchmod to restore the full mode including setuid/setgid/sticky bits
  • copy xattrs (iterate with listxattr / setxattr)

Alternatively, open-and-truncate (open(path, O_WRONLY|O_TRUNC)) preserves inode identity (and thus hardlinks and xattrs), but sacrifices atomicity.

Error Messages/Logs

Steps to Reproduce

1. Group ownership is reset

echo "test" > foo.txt
chown user:docker foo.txt        # set group to docker
# Edit foo.txt via Claude Code
stat foo.txt                     # Gid reverts to user's primary group

Before: Gid: ( 144/ docker)
After: Gid: ( 1001/ martin) ← silently reset

---

2. setuid/setgid/sticky bits are stripped

echo "test" > foo.py
chmod 4755 foo.py                # -rwsr-xr-x
# Edit foo.py via Claude Code
stat foo.py                      # → 0755 -rwxr-xr-x (setuid gone)

Before: Access: (4755/-rwsr-xr-x)
After: Access: (0755/-rwxr-xr-x) ← setuid bit silently stripped

---

3. Extended attributes (xattrs) are lost

echo "test" > foo.txt
setfattr -n user.custom -v "hello" foo.txt
# Edit foo.txt via Claude Code
getfattr -d foo.txt              # → (empty)

Before: user.custom="hello"
After: (no xattrs) ← xattr silently deleted

---

4. Hardlinks are broken

echo "test" > foo.txt
ln foo.txt bar.txt               # both point to the same inode
# Edit foo.txt via Claude Code
cat bar.txt                      # → still shows old content
stat foo.txt                     # new inode
stat bar.txt                     # old inode — link is broken

Before: both files share one inode, Links: 2
After: two separate inodes, each with Links: 1 — the hardlink is silently broken and bar.txt diverges

Claude Model

None

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.145

Platform

Anthropic API

Operating System

Ubuntu/Debian Linux

Terminal/Shell

Other

Additional Information

_No response_

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗