الشقيق الأشهر في عائلة أخطاء الويب:
404 Not Found
The requested URL was not found on this server.
معنى خطأ 404
404 Not Found رمز حالة في HTTP معناه: الخادم يعمل، واستقبل طلبك، ولم يجد شيئًا
على هذا المسار. عكس أخيه الخطأ 500 تمامًا: هناك الخادم
نفسه تعطّل، وهنا الخادم بصحة ممتازة والعنوان هو المشكلة. وإن لم يرد أي خادم
أصلًا فذلك خطأ آخر تمامًا: ERR_CONNECTION_REFUSED.
| تراه بهذا الشكل | من أين |
|---|---|
404 Not Found | خادم ويب (Nginx أو Apache) أو صفحة الموقع |
404: This page could not be found. | صفحة Next.js الافتراضية |
Cannot GET /api/user | Express حين لا يوجد مسار مطابق |
HTTP Error 404.0 - Not Found | خوادم Windows (IIS) |
حالة 404 في تبويب Network أو res.status | طلب fetch أو API |
إن كنت زائرًا
العطل ليس في جهازك ولا في متصفحك، فلا تحذف الكاش ولا تغيّر إعداداتك. جرّب:
- اقرأ الرابط حرفًا حرفًا: شرطة ناقصة، أو حرف كبير بدل صغير، أو نقطة في آخره بعد نسخه من رسالة.
- اصعد خطوة: احذف الجزء الأخير من الرابط (
/blog/old-post←/blog)، فغالبًا تجد القسم وفيه الصفحة. - ابحث داخل الموقع عن عنوان الصفحة. إن وصلت من جوجل، فالصفحة نُقلت أو حُذفت بعد أن فهرسها.
إن كنت صاحب الموقع
| السبب | العلامة | الحل |
|---|---|---|
| رابط تغيّر بلا تحويل | صفحة قديمة كانت تعمل | تحويل 301 |
| حساسية الأحرف | يعمل محليًا (ويندوز) لا على الخادم (لينكس) | أسماء ملفات بأحرف صغيرة |
| روابط SPA بعد النشر | يعمل بالتنقل وينكسر بالتحديث | rewrite إلى index.html |
| WordPress: الروابط الدائمة | كل المقالات 404 فجأة | إعادة حفظ Permalinks |
| ملف لم يُرفع أصلًا | صورة أو ملف واحد ميت | ارفعه وتحقق من المسار |
| رابط داخلي خاطئ | 404 من صفحاتك نفسها | صحّح المصدر |
1) غيّرت الروابط؟ التحويل 301 ليس اختياريًا
أعدت هيكلة الموقع أو غيّرت رابط مقالة؟ كل رابط قديم بلا تحويل خسارة مزدوجة: زائر يرتد، وترتيب متراكم يتبخر. التحويل الدائم 301 ينقل الاثنين للعنوان الجديد:
// Next.js — next.config.js
module.exports = {
async redirects() {
return [{ source: "/old-post", destination: "/blog/new-post", permanent: true }];
},
};
# Apache (.htaccess)
Redirect 301 /old-page https://example.com/new-page
# Nginx
location = /old-page { return 301 /new-page; }
حوّل إلى الصفحة البديلة الأقرب فعلًا، لا إلى الصفحة الرئيسية. جوجل يعامل تحويل كل شيء إلى الرئيسية معاملة 404 تقريبًا (soft 404)، والزائر يضيع أيضًا.
وأين تجد الروابط الميتة المهمة؟ في Google Search Console ← Pages ← Not found (404): قائمة بما حاول جوجل الوصول إليه وفشل. رتّبها حسب الأهمية، وحوّل ما كان له زوار أو روابط خارجية.
2) حساسية الأحرف: فخ «يعمل عندي»
ويندوز وmacOS (افتراضيًا) لا يفرّقان بين Logo.png وlogo.png، وخوادم لينكس تفرّق
بصرامة. النتيجة: يعمل محليًا وينكسر في الإنتاج. القاعدة: كل أسماء الملفات
والمسارات بأحرف صغيرة وبشرطات بدل المسافات.
3) تطبيقات SPA: التحديث يكسر الصفحة
أشهر 404 عند مطوري React وVue: التنقل يعمل، وF5 على /about يعطي 404. السبب أن
الخادم لا يعرف مساراتك الداخلية، والتطبيق كله في index.html. الحل rewrite يعيد
كل مسار غير موجود إلى index.html:
# Netlify — ملف public/_redirects
/* /index.html 200
في Vercel، ملف vercel.json بجذر تطبيق Vite:
{ "rewrites": [{ "source": "/(.*)", "destination": "/index.html" }] }
# Nginx
location / { try_files $uri $uri/ /index.html; }
خادم تطوير Vite يفعل هذا تلقائيًا، لذلك لا تظهر المشكلة إلا بعد النشر. وتطبيقات Next.js لا تحتاجه أصلًا: كل مسار صفحة حقيقية على الخادم.
وانتبه لأثره الجانبي: بعد هذا الـ rewrite يعيد الخادم index.html بالحالة 200 لأي
رابط، حتى غير الموجود، أي soft 404. اعرض صفحة «غير موجود» داخل التطبيق، وأضف
<meta name="robots" content="noindex"> إليها.
4) WordPress: كل شيء 404 فجأة
المقالات كلها انكسرت بعد نقل أو تحديث؟ الغالب .htaccess أو إعدادات الروابط:
الإعدادات ← الروابط الدائمة ← حفظ بلا أي تغيير، فيعيد توليد القواعد. استمر؟
راجع ملف .htaccess نفسه، وتأكد أن mod_rewrite مفعّل في Apache.
إن كنت مطورًا: 404 في الكود
Cannot GET /api/user في Express
app.get("/api/users", (req, res) => res.json([]));
جرّبنا ثلاثة طلبات على هذا التطبيق (Express 5):
| الطلب | الرد |
|---|---|
GET /api/user | 404 Cannot GET /api/user (خطأ إملائي في المسار) |
POST /api/users | 404 Cannot POST /api/users (المسار موجود، لكن لـ GET فقط) |
GET /api/users/ | 200 (Express يتسامح مع الشرطة الأخيرة افتراضيًا) |
الدرس الثاني هو المفاجئ: طريقة HTTP خاطئة تعطي 404 لا 405 في Express. تأكد أن
fetch يرسل نفس الطريقة المسجلة (method: "POST") وأن المسار يطابق حرفيًا، وأن
app.use("/api", router) لا يضيف بادئة مكررة. وإن كان الخطأ يصل للواجهة، فلا تقرأ
الرد كـ JSON قبل فحص res.ok، وإلا ظهر لك
Unexpected token in JSON بدل 404 الحقيقي.
404: This page could not be found. في Next.js
هذه صفحة Next.js الافتراضية حين لا يطابق الرابط أي مسار، أو حين يستدعي الكود
notFound(). جرّبناها في تطبيق Next.js 16: الحالة 404، والعنوان
404: This page could not be found.. أسبابها الشائعة:
- الملف في المكان الخطأ: صفحة
/aboutتحتاجapp/about/page.tsx، والمجلد وحده لا يكفي. - مسار ديناميكي:
app/blog/[slug]/page.tsxموجود، لكن الكود يستدعيnotFound()حين لا يجد المقالة. (بالتفصيل في درس المسارات الديناميكية.) - معالج API:
app/api/users/route.tsيصدّرGETفقط، والطلبPOST. هنا يرد Next.js بـ405لا 404، فاقرأ الرقم. (معالجات المسارات.)
ولصفحة 404 مخصصة: ملف app/not-found.tsx، وNext.js يرسله بالحالة 404. استثناء
يذكره توثيق Next.js 16 نفسه: إن استُدعي notFound() بعد أن بدأ بث الصفحة (داخل
Suspense أو مع loading.tsx)، تبقى الحالة 200، ويضيف Next.js
<meta name="robots" content="noindex"> حتى لا تُفهرس. إن احتجت 404 حقيقية، فتحقق من
وجود المحتوى قبل بدء العرض.
حوّل صفحة 404 من طريق مسدود إلى بداية
الافتراضية تقول «انتهت الرحلة». المخصصة الذكية تقول «تفضّل من هنا»:
- رسالة ودودة، وبحث، وروابط لأهم الأقسام (جرّب رابطًا عشوائيًا على موقعنا 😄).
- الأهم تقنيًا: أن ترد بحالة 404 حقيقية لا 200، وإلا صارت soft 404 تُحسب صفحة فارغة ضد جودة موقعك.
قائمة تحقّق سريعة
- زائر؟ صحّح الرابط، واصعد خطوة، وابحث داخل الموقع.
- Search Console ← Pages ← 404: قائمة الروابط التي تخسرها. حوّل المهم بـ 301 لبديل حقيقي.
- أسماء ملفات بأحرف صغيرة دائمًا.
- SPA؟ rewrite لـ
index.htmlقبل النشر، وصفحة «غير موجود» بـ noindex. - WordPress؟ إعادة حفظ الروابط الدائمة.
- Express
Cannot POST؟ الطريقة لا المسار. - Next.js؟ مكان
page.tsx، وnotFound()، و405 لمعالجات API.
الخلاصة
404 أصدق من 500 وأسهل: العنوان خاطئ أو المحتوى انتقل. صحّح المصادر، وحوّل القديم بـ 301 لبديل حقيقي، واضبط rewrite تطبيقات SPA، واجعل صفحة الخطأ نفسها نقطة انطلاق للزائر.
رموز الحالة كلها في درس HTTP ضمن مسار الشبكات بالعربي، وأكمل مع حل خطأ 500 Internal Server Error وحل خطأ CORS.