Sửa lỗi WordPress "Upload: Failed to Write File to Disk"

intermediate📝 WordPress2026-05-31| WordPress 5.x/6.x trên Linux (Ubuntu, Debian, CentOS/RHEL) với Apache hoặc Nginx + PHP 7.4–8.3

Error Message

Upload: Failed to Write File to Disk
#wordpress#upload#permissions#filesystem

Tình Huống

Bạn đang dùng trình tải lên media của WordPress để đưa ảnh hoặc PDF lên. Thanh tiến trình chạy đến cuối... rồi không có gì xảy ra. Thông báo lỗi xuất hiện:

Upload: Failed to Write File to Disk

Không có file nào trong thư viện media. Không có gì trên đĩa. Chỉ có mỗi thông báo đó. Dưới đây là cách truy tìm nguyên nhân và khắc phục.

Chuyện Gì Đang Xảy Ra

Quá trình upload trong WordPress diễn ra theo hai bước riêng biệt: PHP ghi file vào thư mục tạm trước, sau đó mới chuyển nó sang wp-content/uploads/. Hỏng bước nào là bạn gặp lỗi này. Có bốn nguyên nhân chính:

  • Sai quyền trên thư mục wp-content/uploads/ — user của web server không có quyền ghi vào đó
  • Thư mục tạm của PHP không có quyền ghi — bước ghi tạm thất bại trước khi WordPress kịp chuyển file
  • Thư mục uploads không tồn tại — thường xảy ra sau khi migrate hoặc restore không đầy đủ
  • Đĩa hoặc quota inode đã đầy — không còn dung lượng, không gì được ghi

Chẩn Đoán Nhanh

SSH vào server và chạy ba lệnh kiểm tra sau trước khi thay đổi bất cứ thứ gì.

1. Kiểm tra dung lượng đĩa

df -h /var/www/html

Nếu đã đạt 100%, hãy giải phóng dung lượng trước. Cũng nên kiểm tra inode — một thư mục chứa 50.000 file nhỏ có thể cạn kiệt inode trong khi dung lượng block vẫn còn trống:

df -i /var/www/html

2. Kiểm tra thư mục uploads

ls -la /var/www/html/wp-content/uploads/

Thư mục phải được sở hữu bởi user của web server — www-data trên Ubuntu/Debian, apache trên CentOS/RHEL — và có quyền ghi được thiết lập đúng.

3. Kiểm tra thư mục tạm của PHP

php -r "echo ini_get('upload_tmp_dir') ?: sys_get_temp_dir();"

Ghi nhớ đường dẫn mà lệnh trả về. Xác nhận thư mục đó có quyền ghi cho user của web server trước khi tiếp tục.

Cách Khắc Phục

Cách 1: Sửa quyền thư mục uploads (giải quyết ~90% trường hợp)

Trước tiên, xác định user web server thực tế của bạn:

# Ubuntu/Debian
ps aux | grep -E '(apache|nginx|php-fpm)' | grep -v root | head -1

# Hoặc kiểm tra cấu hình pool PHP-FPM
grep -r "user = " /etc/php/*/fpm/pool.d/

Sau đó sửa ownership và quyền:

# Thay www-data bằng user web server thực tế của bạn
sudo chown -R www-data:www-data /var/www/html/wp-content/uploads/
sudo chmod -R 755 /var/www/html/wp-content/uploads/

Trên shared hosting nơi PHP chạy với tài khoản user của chính bạn, 775 thường là lựa chọn phù hợp:

sudo chmod -R 775 /var/www/html/wp-content/uploads/

Cách 2: Tạo thư mục uploads nếu nó bị thiếu

sudo mkdir -p /var/www/html/wp-content/uploads
sudo chown -R www-data:www-data /var/www/html/wp-content/uploads/
sudo chmod -R 755 /var/www/html/wp-content/uploads/

WordPress cũng có thể tự tạo lại cấu trúc thư mục. Vào Settings → Media trong wp-admin và nhấn Save — WordPress sẽ cố tạo đường dẫn uploads khi phát hiện nó bị thiếu.

Cách 3: Sửa quyền thư mục tạm của PHP

Thư mục uploads trông ổn nhưng lỗi vẫn còn? Bước ghi tạm có thể đang thất bại trước khi WordPress kịp chuyển file.

# Lấy đường dẫn tạm chính xác mà PHP đang dùng
php -r "echo ini_get('upload_tmp_dir') ?: sys_get_temp_dir();"

# Sửa /tmp nếu đó là kết quả trả về
sudo chmod 1777 /tmp

Đang dùng thư mục tạm tùy chỉnh trong cấu hình pool PHP-FPM? Sửa trực tiếp đường dẫn đó:

grep upload_tmp_dir /etc/php/*/fpm/pool.d/*.conf
sudo chown www-data:www-data /path/to/custom/tmp
sudo chmod 755 /path/to/custom/tmp

Cách 4: Bật debug logging để tìm đường dẫn gây lỗi chính xác

Vẫn chưa ra? Bật debug logging trong wp-config.php tạm thời:

define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);

Thử upload lại. Sau đó mở wp-content/debug.log — lỗi PHP đầy đủ sẽ bao gồm đường dẫn file chính xác mà WordPress đang cố ghi vào, giúp vấn đề trở nên rõ ràng ngay.

CentOS/RHEL: Kiểm Tra SELinux

Trên CentOS hoặc RHEL, SELinux thường là thủ phạm ẩn. Quyền Unix trông đúng, nhưng việc ghi vẫn thất bại im lặng.

# Kiểm tra SELinux có đang ở chế độ enforcing không
getenforce

# Khôi phục context SELinux đúng cho thư mục uploads
sudo restorecon -Rv /var/www/html/wp-content/uploads/

# Hoặc cho phép web server ghi file một cách tổng quát
sudo setsebool -P httpd_unified 1

Xác Nhận Đã Khắc Phục

  • Vào Media → Add New trong wp-admin
  • Upload một ảnh thử nghiệm
  • Xác nhận nó xuất hiện trong thư viện media cùng thumbnail được tạo
  • Kiểm tra file đã thực sự có trên đĩa:
ls -la /var/www/html/wp-content/uploads/$(date +%Y/%m)/

File của bạn phải có ở đó, được sở hữu bởi www-data.

Phòng Ngừa

Khi điều chỉnh quyền thư mục, tôi dùng Unix Permissions Calculator trên ToolCraft để kiểm tra lại giá trị chmod trước khi chạy — nó hiển thị số octal chính xác từ các checkbox, rất tiện khi bạn đang phân vân lúc 2 giờ sáng. Chạy hoàn toàn trên trình duyệt, không upload gì cả.

Một script theo dõi dung lượng đĩa trong cron sẽ phát hiện vấn đề quota trước khi gây ra sự cố:

#!/bin/bash
THRESHOLD=85
USAGE=$(df /var/www/html | awk 'NR==2 {print $5}' | sed 's/%//')
if [ "$USAGE" -gt "$THRESHOLD" ]; then
  echo "Disk at ${USAGE}% on $(hostname)" | mail -s "[Alert] Disk Space" admin@yourdomain.com
fi
# Thêm vào cron
*/30 * * * * /usr/local/bin/check-disk.sh

Một lưu ý nữa: hãy loại trừ thư mục uploads khỏi bất kỳ script dọn dẹp nào quét các file tạm cũ. Những script xoay vòng log hung hăng trỏ sai đường dẫn đã xóa sạch cả thư mục uploads — đó là bài học đau đớn mà không ai muốn học theo cách đó.

Related Error Notes