پرش به محتوا
سرور و .htaccess

نوشته‌های وردپرس خطای ۴۰۴ می‌دهند اما صفحه اصلی کار می‌کند

اگر صفحه اصلی سایت شما درست بارگذاری می‌شود اما تک‌تک نوشته‌ها و برگه‌ها خطای ۴۰۴ می‌دهند، یعنی کدهای بازنویسی نشانی (URL rewrite) که وردپرس به آن‌ها متکی است، در فایل شما گم یا خراب شده‌اند.

منتشرشده

اگر صفحه اصلی سایت شما درست بارگذاری می‌شود اما تک‌تک نوشته‌ها و برگه‌ها خطای ۴۰۴ می‌دهند، یعنی کدهای بازنویسی نشانی (URL rewrite) که وردپرس به آن‌ها متکی است، در فایل .htaccess شما گم یا خراب شده‌اند. سریع‌ترین راه‌حل: در پیشخوان وردپرس به تنظیمات ← پیوندهای یکتا بروید و بدون تغییر هیچ چیزی، روی ذخیره تغییرات کلیک کنید. این کار وردپرس را وادار می‌کند بلوک بازنویسی را دوباره بسازد. اگر خطای ۴۰۴ همچنان باقی ماند، یعنی فایل .htaccess شما برای وب‌سرور قابل نوشتن نیست، آپاچی طوری پیکربندی شده که آن را نادیده می‌گیرد، یا شما روی Nginx هستید (که اصلاً از .htaccess استفاده نمی‌کند).

چرا صفحه اصلی کار می‌کند اما نوشته‌ها نه

صفحه اصلی شما کار می‌کند چون درخواست به / مستقیماً از index.php در ریشه سایت پاسخ داده می‌شود. هیچ بازنویسی‌ای لازم نیست.

اما درخواست به /2026/my-post/ فرق دارد. این مسیر یک پوشه واقعی روی دیسک نیست. برای اینکه وردپرس به آن پاسخ دهد، آپاچی باید درخواست را به‌صورت داخلی به index.php هدایت کند، و وردپرس سپس REQUEST_URI را می‌خواند، آن را با کدهای بازنویسی ذخیره‌شده در گزینه rewrite_rules در پایگاه داده تطبیق می‌دهد، متغیرهای کوئری را حل می‌کند (WP::parse_request()) و نوشته درست را بارگذاری می‌کند.

تحویل درخواست از آپاچی به index.php همان بخشی است که خراب می‌شود. این کار کاملاً به این بلوک در .htaccess وابسته است:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

دو خط RewriteCond می‌گویند: اگر مسیر درخواست‌شده یک فایل واقعی نیست (!-f) و یک پوشه واقعی هم نیست (!-d)، آن را به index.php بفرست. این بلوک را حذف کنید و آپاچی دنبال یک پوشه واقعی با نام /2026/my-post/ می‌گردد، آن را پیدا نمی‌کند، و خطای ۴۰۴ خودش را برمی‌گرداند — پیش از آنکه وردپرس اصلاً درخواست را ببیند.

چرا وردپرس هنگام ذخیره پیوندهای یکتا فایل .htaccess را بازنویسی می‌کند

این همان بخشی است که بیشتر راهنماها از آن می‌گذرند. وقتی در صفحه پیوندهای یکتا روی ذخیره کلیک می‌کنید، وردپرس تابع flush_rewrite_rules() را فراخوانی می‌کند. روی آپاچی با یک .htaccess قابل نوشتن، این کار تابع save_mod_rewrite_rules() را فعال می‌کند که بلوک بالا را از طریق WP_Rewrite::mod_rewrite_rules() دوباره می‌سازد و آن را با insert_with_markers() دوباره در فایل می‌نویسد.

insert_with_markers() فقط خطوط بین # BEGIN WordPress و # END WordPress را دست می‌زند. هر چیزی بیرون از این نشانگرها دست‌نخورده باقی می‌ماند. هر چیزی داخل آن‌ها دور ریخته و بازنویسی می‌شود. نسخه‌های جدیدتر وردپرس حتی این هشدار را مستقیم داخل فایل چاپ می‌کنند:

هرگونه تغییر در دستورهای بین این نشانگرها بازنویسی خواهد شد.

پس این جمله که «وردپرس فایل .htaccess من را بازنویسی می‌کند» درست است اما محدود: وردپرس فقط بلوک نشانه‌گذاری‌شده خودش را بازنویسی می‌کند، و فقط زمانی که فایل قابل نوشتن باشد. اگر فایل قابل نوشتن نباشد، ذخیره‌کردن بی‌سروصدا هیچ تغییری روی دیسک ایجاد نمی‌کند. وردپرس یک اعلان زرد در صفحه پیوندهای یکتا نشان می‌دهد که از شما می‌خواهد کدها را دستی جای‌گذاری کنید، و اگر آن اعلان را از دست بدهید، بلوک بازنویسی شما همچنان گم می‌ماند و هر نوشته همچنان خطای ۴۰۴ می‌دهد.

چطور آن را به‌ترتیب رفع کنیم

۱. پیوندهای یکتا را دوباره ذخیره کنید. تنظیمات ← پیوندهای یکتا ← ذخیره تغییرات. نیازی به هیچ ویرایشی نیست. این کار فرایند flush را دوباره اجرا می‌کند و بلوک را بازنویسی می‌کند. این کار بیشتر موارد را حل می‌کند، از جمله کدهای قدیمی پس از یک مهاجرت.

۲. بررسی کنید که .htaccess وجود دارد و قابل نوشتن است. این فایل در همان پوشه‌ای است که wp-config.php قرار دارد. یک فایل مخفی (dotfile) است، پس در نرم‌افزار FTP خود گزینه «نمایش فایل‌های مخفی» را فعال کنید یا از این دستور استفاده کنید:

ls -la /path/to/wordpress/.htaccess

اگر فایل وجود ندارد، آن را بسازید و بلوک درست را در آن جای‌گذاری کنید. اگر وردپرس شما در یک زیرشاخه نصب شده، مقدار RewriteBase و هدف نهایی بازنویسی باید با آن مسیر مطابقت داشته باشند — اشتباه‌کردن در همین نکته رایج‌ترین دلیلی است که یک بلوک دستی‌جای‌گذاری‌شده باز هم خطای ۴۰۴ می‌دهد. سازنده .htaccess ما دقیقاً بلوک مناسب مسیر نصب شما را می‌سازد تا مجبور نباشید حدس بزنید.

۳. مطمئن شوید آپاچی اجازه خواندن .htaccess را دارد. اگر میزبان مجازی (virtual host) روی AllowOverride None تنظیم شده باشد، آپاچی فایل را کاملاً نادیده می‌گیرد، فارغ از محتوای آن. شما به AllowOverride All (یا دست‌کم FileInfo) روی پوشه وردپرس نیاز دارید. این تنظیم در پیکربندی سرور است، نه در .htaccess، پس نیاز به دسترسی سرور دارد:

<Directory /var/www/html>
    AllowOverride All
</Directory>

۴. مطمئن شوید mod_rewrite فعال است. روی Debian/Ubuntu:

sudo a2enmod rewrite
sudo systemctl restart apache2

۵. روی Nginx، فایل .htaccess وجود ندارد. به‌جای آن، کدهای بازنویسی داخل بلوک سرور قرار می‌گیرند:

location / {
    try_files $uri $uri/ /index.php?$args;
}

عیب‌یابی سریع: خطای ۴۰۴ مال کیست؟

به صفحه خطای ۴۰۴ نگاه کنید. اگر یک صفحه خطای بدون استایل از آپاچی یا میزبان است، یعنی آپاچی هیچ‌وقت به وردپرس نرسیده — این یک مشکل .htaccess یا پیکربندی سرور است (مراحل ۲ تا ۴). اما اگر صفحه ۴۰۴ استایل‌دار خودِ قالب شماست، یعنی وردپرس درخواست را دریافت می‌کند اما نمی‌تواند آن را تطبیق دهد — کدهای داخل پایگاه داده قدیمی هستند و ذخیره دوباره پیوندهای یکتا (مرحله ۱) راه‌حل است. همین یک تمایز، جلوی یک ساعت حدس‌زدن را برای بیشتر افراد می‌گیرد.

چه کارهایی نباید کرد

اول همه افزونه‌ها را غیرفعال نکنید. نشانه خالص «نوشته‌ها ۴۰۴ می‌دهند، صفحه اصلی کار می‌کند» یک مشکل بازنویسی است، نه تداخل افزونه. غیرفعال‌کردن افزونه‌ها پاسخ غریزی در انجمن‌هاست و تقریباً هیچ‌وقت به این مشکل ربط ندارد.

فایل .htaccess خود را chmod 777 نکنید. وردپرس نیاز دارد فایل توسط کاربر وب‌سرور قابل نوشتن باشد، که با قابل‌نوشتن‌بودن برای همه فرق دارد. دسترسی 644 با مالک درست، خوب و امن است؛ 777 یک حفره امنیتی است که در ضمن مشکل مسیریابی را هم حل نمی‌کند.

کدهای بازنویسی سفارشی را داخل نشانگرهای # BEGIN WordPress / # END WordPress جای‌گذاری نکنید. دفعه بعد که هر کسی پیوندهای یکتا را ذخیره کند، این کدها پاک می‌شوند. دستورهای سفارشی را بالای خط # BEGIN WordPress قرار دهید.

وردپرس را دوباره نصب نکنید. فایل‌های هسته سالم‌اند. این فقط یک بلوک متنی گم‌شده است، نه یک نصب خراب.

قالب خود را مقصر ندانید. مسیریابی پیوندهای یکتا بخشی از هسته وردپرس است. یک قالب نه می‌تواند آن را ایجاد کند و نه می‌تواند آن را رفع کند.

هنوز گیر کرده‌اید؟

اگر پیوندهای یکتا را دوباره ذخیره کرده‌اید، وجود و قابل‌نوشتن‌بودن بلوک را تأیید کرده‌اید و AllowOverride All را تنظیم کرده‌اید، مظنون باقی‌مانده یک افزونه امنیتی یا یک قانون در سطح میزبان است که پشت پرده فایل .htaccess را دوباره می‌سازد یا قفل می‌کند. زمان تغییر (modification timestamp) فایل را درست بعد از ذخیره پیوند یکتا بررسی کنید — اگر تغییر نکرده بود، چیزی جلوی نوشتن را می‌گیرد. یک بلوک تمیز با سازنده .htaccess بسازید، آن را جای‌گذاری کنید و با یک بارگذاری مجدد کامل (hard refresh) دوباره آزمایش کنید.