Troubleshooting rsync Error: 'some files could not be transferred permissions' on Linux

Resolve 'rsync some files could not be transferred permissions' errors by understanding user contexts, file ownership, and applying correct `rsync` flags or `chmod`/`chown` on Linux systems.


rsync is an incredibly versatile utility for syncing files and directories, locally and remotely. However, one of the most common stumbling blocks encountered by system administrators and developers is the dreaded “some files could not be transferred permissions” error. This guide will delve into the underlying causes and provide a structured, step-by-step resolution process, ensuring your file transfers complete successfully.

Symptom & Error Signature

When attempting to synchronize files using rsync, particularly to a remote host, the command may execute partially, displaying warnings or errors about specific files or directories that could not be transferred due to permission issues. The rsync process might exit with a non-zero status code, and the output will typically look like this:

rsync -avzP /source/path/ user@remote:/destination/path/

Expected output with errors:

sending incremental file list
./
file1.txt
file2.log
directory_a/
directory_a/subfile.conf
rsync: [generator] chown "/destination/path/file1.txt" failed: Operation not permitted (1)
rsync: [generator] mkstemp "/destination/path/.directory_a.d2023-11-09-15-30-01" failed: Permission denied (13)
rsync: [generator] chmod "/destination/path/file2.log" failed: Operation not permitted (1)
rsync: [receiver] failed to set times on "/destination/path/file1.txt": Operation not permitted (1)
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1805) [generator=3.2.7]
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1196) [receiver=3.2.7]

The key indicators are “Operation not permitted” (error code 1) and “Permission denied” (error code 13), often accompanied by rsync error: some files/attrs were not transferred (code 23).

Root Cause Analysis

The “permission denied” error during an rsync operation fundamentally means that the user account attempting to perform an action (e.g., create a file, change ownership, set permissions, modify timestamps) on the destination system lacks the necessary privileges for that specific action or directory.

Here’s a breakdown of common root causes:

  1. Incorrect Destination Directory Permissions/Ownership:

    • The most frequent cause. The user account executing rsync on the destination machine (typically via SSH) does not have write permissions to the target directory or its parent directories.
    • Similarly, if rsync attempts to create new files or directories, the umask of the destination user might be too restrictive, or the default group ownership is incorrect.
  2. rsync Flags Preserving Ownership/Permissions (-a, -pog):

    • The -a (archive) flag, commonly used for its convenience, implicitly includes -pog (preserve permissions, owner, group).
    • If rsync is run as a non-root user on the source but attempts to preserve source root ownership or specific user/group ownership on the destination where that user/group doesn’t exist or the destination user lacks privileges, the chown or chmod operations will fail.
    • Preserving permissions (mode) also requires the destination user to have the authority to set those specific modes.
  3. Insufficient Privileges on the Destination Host:

    • The SSH user connecting to the remote host might not have sudo privileges, or the sudo configuration (/etc/sudoers) is too restrictive, preventing rsync from executing privileged commands remotely.
    • If rsync attempts to create or modify files owned by root or another user/group on the destination, and the rsync user is not root and lacks sudo access, these operations will fail.
  4. ACLs (Access Control Lists):

    • Less common than standard Linux permissions, but ACLs can override or supplement traditional rwx permissions. If an ACL is configured on the destination path to deny access to the rsync user, it will cause permission errors.
  5. SELinux or AppArmor Interference:

    • Security modules like SELinux (on CentOS/RHEL) or AppArmor (on Ubuntu/Debian) can restrict what processes (including rsync or the sshd daemon it uses) can do, even if standard file permissions appear correct. They might prevent writes to certain directories or prevent the chown/chmod operations.

Step-by-Step Resolution

Follow these steps to diagnose and resolve rsync permission errors.

1. Verify User and Destination Directory Permissions

First, identify the user context rsync is operating under on the destination system and check the permissions of the target directory.

1.1 Identify the Remote User: The user performing the rsync operation on the remote host is typically the user specified in the SSH connection (e.g., user@remote).

1.2 Check Destination Directory Permissions: Log into the remote host as the rsync user and check the permissions of the target directory (/destination/path/ in our example).

# Log in to the remote server
ssh user@remote

# Check permissions of the destination directory
ls -ld /destination/path/

# Example output:
# drwxr-xr-x 3 root root 4096 Nov 9 15:00 /destination/path/

In this example, /destination/path/ is owned by root:root and only root has write (w) permissions. If user is not root, they cannot write here.

Also check parent directories if /destination/path/ doesn’t exist yet and rsync needs to create it.

ls -ld /destination/
# Example: drwxr-xr-x 5 root root 4096 Oct 1 10:00 /destination/

2. Adjust Destination Directory Ownership and Permissions

Based on the verification, you’ll likely need to grant the remote user write access.

2.1 Change Ownership (chown): If the destination directory is owned by root or another user, and you want user to own it, change ownership. This usually requires sudo.

# On the remote host, as a user with sudo privileges
sudo chown -R user:user /destination/path/

[!IMPORTANT] Replace user:user with the actual username and group that will be performing the rsync. For web content (e.g., Nginx, Apache), you might use www-data:www-data or a specific application user.

2.2 Change Permissions (chmod): Ensure the owner has write permissions.

# On the remote host, as a user with sudo privileges or the owner
sudo chmod -R u+rwX /destination/path/

The +X (capital X) flag is useful for directories, as it sets the execute bit only if the file is a directory or already has the execute bit set for some user. This helps maintain appropriate permissions for files vs. directories.

3. Re-run rsync with Appropriate Flags

Re-evaluate your rsync command flags. The -a (archive) flag preserves permissions, ownership, and timestamps. If your goal is not to preserve these from the source, but rather for the destination system’s default permissions/ownership to apply, then you should adjust your flags.

3.1 If you DO NOT want to preserve owner/group/permissions from source: This is common when syncing application files to a web server where the www-data user should own them, regardless of source ownership. Remove -pog from your command. If using -a, remove it and use -rvz or explicitly disable them.

# Explicitly disable preservation of permissions, owner, and group
rsync -rvz --no-p --no-o --no-g /source/path/ user@remote:/destination/path/

# Or, if you primarily care about recursive, verbose, compressed transfer
rsync -rvz /source/path/ user@remote:/destination/path/

3.2 If you DO want to preserve owner/group/permissions from source (and chown/chmod failed): This implies that the remote user needs permission to change ownership and permissions. This typically requires sudo on the remote side.

# Use rsync with --rsync-path to invoke sudo on the remote end
# This tells rsync to use 'sudo rsync' instead of just 'rsync' on the remote.
rsync -avzP -e "ssh" /source/path/ user@remote:/destination/path/ --rsync-path="sudo rsync"

[!WARNING] Using --rsync-path="sudo rsync" grants significant power to the remote rsync process, allowing it to modify files anywhere sudo rsync is permitted. Use with extreme caution and ensure your sudoers configuration is secure. This should ideally be restricted to specific paths.

Alternatively, if you’re transferring as root from the source (e.g., within a CI/CD pipeline or a dedicated backup system) and want to chown to a specific user on the destination:

# 1. Sync files as root (or a user with appropriate permissions)
rsync -avzP /source/path/ root@remote:/destination/path/

# 2. After transfer, log into the remote host and adjust ownership/permissions
ssh root@remote 'chown -R www-data:www-data /destination/path/'
ssh root@remote 'chmod -R u=rwX,go=rX /destination/path/'

[!WARNING] Directly rsyncing as root can be dangerous if not carefully managed. Ensure you are syncing to the correct, intended destination path to avoid overwriting critical system files.

4. Check for ACLs (Access Control Lists)

If standard chmod/chown doesn’t resolve the issue, ACLs might be in play.

4.1 Check Existing ACLs:

# On the remote host
getfacl /destination/path/

Look for any deny rules or specific user/group entries that might conflict.

4.2 Set or Modify ACLs (if necessary): To grant specific access to a user, for example:

# On the remote host, as a user with sudo privileges
sudo setfacl -m u:user:rwx /destination/path/
sudo setfacl -m d:u:user:rwx /destination/path/ # For default permissions on new files/directories

[!IMPORTANT] ACLs can add complexity. Ensure you understand their implications before modifying them. In most standard setups, they are not present or required.

5. Investigate SELinux or AppArmor (Advanced)

If all else fails and you’re on a system with SELinux or AppArmor enabled, these security enhancements might be blocking the rsync operation.

5.1 Check SELinux Status (CentOS/RHEL):

# On the remote host
getenforce
sestatus

If getenforce returns Enforcing, SELinux is active. Check /var/log/audit/audit.log for AVC (Access Vector Cache) denial messages.

A common fix is to relabel the directory context:

# On the remote host, if applicable for your rsync scenario
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/destination/path(/.*)?"
sudo restorecon -Rv /destination/path/

[!WARNING] Temporarily disabling SELinux (sudo setenforce 0) for testing is possible, but it should never be done in a production environment without fully understanding the security implications and having a plan to re-enable it.

5.2 Check AppArmor Status (Ubuntu/Debian):

# On the remote host
sudo apparmor_status

If AppArmor is loaded, check /var/log/syslog or dmesg for denial messages related to rsync or sshd.

If AppArmor is blocking, you might need to adjust the profile for rsync or sshd, which is highly environment-specific and requires deep knowledge of AppArmor profiles.

6. Sanity Check: Test with a Small, Simple File

Before attempting a large transfer, create a small test file and try to transfer it to an empty directory on the destination. This helps isolate the problem to the permissions of the target directory rather than specific files within your larger transfer.

# On source
echo "test content" > /tmp/testfile.txt

# On remote, ensure the test directory exists and has correct permissions
ssh user@remote 'mkdir -p /destination/test_dir; chmod u+rwx /destination/test_dir;'

# Attempt transfer
rsync -avzP /tmp/testfile.txt user@remote:/destination/test_dir/

By systematically addressing user context, file permissions, rsync flags, and environmental security measures, you can effectively troubleshoot and resolve rsync “permission denied” errors.