تخطّى إلى المحتوى الرئيسي
معالجة الأخطاء في Next.js App Router: ما الذي يلتقطه كل ملف خطأ فعليًا

معالجة الأخطاء في Next.js App Router: ما الذي يلتقطه كل ملف خطأ فعليًا

July 17, 2026
هندسة الواجهات
6 دقيقة قراءة

في Devya نطلق عددًا كبيرًا من تطبيقات Next.js App Router، والعطل المتكرر هو أن استثناءً واحدًا غير معالَج يُسقط الصفحة كاملة بدل اللوحة الواحدة التي تعطلت. يحتوي App Router أصلًا على أدوات لعزل هذا الانفجار عبر مجموعة صغيرة من الملفات الخاصة، شرط أن يعرف الفريق أين يقع كل ملف وما الذي يلتقطه فعليًا. هذه ملاحظاتنا الهندسية حول error.tsx و global-error.tsx و not-found.tsx و الـ digest في الإنتاج ودالة reset.

أبرز النقاط

ملف error.tsx داخل مقطع مسار (route segment) يُنشئ حدود خطأ (error boundary) في React تلتقط الأخطاء التي تُرمى أثناء عرض صفحة ذلك المقطع وأي تخطيطات وصفحات ومكوّنات متداخلة تحته.

يجب أن يبدأ error.tsx بـ 'use client' لأن حدود الخطأ في React تعتمد على دوال دورة حياة الأصناف (class) التي لا تعمل إلا في المتصفح؛ ويستقبل الملف خاصيتين هما error و reset.

لا يستطيع error.tsx التقاط خطأ يُرمى من التخطيط (layout) في المقطع نفسه، لأن ذلك التخطيط يُعرض فوق الحدود — لالتقاطه تضع error.tsx في المقطع الأب.

global-error.tsx هو الحد الوحيد الذي يلتقط أخطاء التخطيط الجذري (root layout)؛ ولأنه يستبدل التخطيط الجذري عند تفعيله فيجب أن يعرض وسمَي html و body الخاصين به، ويعمل في الإنتاج فقط.

في الإنتاج يحذف Next.js نص رسالة الأخطاء القادمة من الخادم ويستبدلها بترميز digest حتى لا يتسرب شيء إلى المتصفح؛ ويُسجَّل الخطأ الأصلي على الخادم بدلًا من ذلك.

ماذا يلتقط error.tsx في App Router؟

يلتقط ملف error.tsx الأخطاء التي تُرمى أثناء عرض مقطع المسار الموجود فيه وكل ما يتداخل تحته. عندما نضعه في مجلد مقطع، يغلّف Next.js تلقائيًا ملف page.tsx لذلك المقطع وتخطيطاته وصفحاته المتداخلة وكل مكوّن خادم أو عميل تعرضه ضمن حدود خطأ في React. وعند رمي خطأ أثناء العرض تستبدل الحدود واجهة error.tsx بدل إزالة الشجرة كلها.

الجزء الذي يربك الفرق هو ما لا يلتقطه error.tsx: الأخطاء المرمية داخل معالجات الأحداث مثل onClick، والأخطاء في الشيفرة غير المتزامنة التي تعمل بعد العرض، واستدعاء notFound()، والخطأ المرمي من layout.tsx أو template.tsx في المقطع نفسه. فملف error.tsx عند app/dashboard/error.tsx يلتقط ما يُرمى من app/dashboard/page.tsx وأي شيء متداخل تحت /dashboard، لكن ليس من app/dashboard/layout.tsx.

لماذا يجب أن يكون error.tsx مكوّن عميل؟

يجب أن يكون error.tsx مكوّن عميل لأن حدود الخطأ في React مبنية على دوال دورة حياة الأصناف — getDerivedStateFromError و componentDidCatch — التي لا تُنفَّذ إلا في المتصفح. يغلّف Next.js الملف ضمن حدود تحتاج بيئة تشغيل العميل، لذا يجب أن يبدأ بـ 'use client'.

يستقبل المكوّن خاصيتين بالضبط. الأولى error، وهي نسخة Error قد تحمل نص digest. والثانية reset، وهي دالة بلا وسائط تعيد عرض الحدود. عادةً يعرض error.tsx تنبيهًا فيه عنوان وزر يستدعي onClick الخاص به دالة reset().

متى نحتاج global-error.tsx بدل error.tsx؟

تحتاج global-error.tsx حين يقع الخطأ في التخطيط الجذري أو القالب الجذري، اللذين يقعان فوق كل error.tsx عادي. فملف error.tsx العادي يُعرض داخل التخطيط الذي يحميه، فلا يمكنه إطلاقًا استبدال تخطيط جذري معطوب.

يقع global-error.tsx في أعلى الشجرة، وعند تفعيله يستبدل التخطيط الجذري كاملًا — ولذلك يجب أن يتضمن وسمَي html و body الخاصين به. وهو فعّال في الإنتاج فقط؛ أما في التطوير فتتولى واجهة أخطاء Next.js العرض ليرى الفريق التتبع الحقيقي. ولأنه يستبدل كل شيء نُبقي ترميزه بسيطًا.

كيف نعالج «غير موجود» بمعزل عن الأخطاء؟

استدعِ notFound() من next/navigation، فهي ترمي خطأ تحكم مخصصًا تلتقطه أقرب not-found.tsx وليس error.tsx. فالسجل المفقود نتيجة متوقعة لا انهيار، ولذلك يستحق حدوده الخاصة وحالة HTTP 404 حقيقية.

استدعاء notFound() داخل مقطع يعرض ملف not-found.tsx لذلك المقطع ويعيد 404 عند التحميل الأول؛ كما يعالج ملف app/not-found.tsx الجذري المسارات التي لا تطابق أي مسار. عمليًا نستدعي notFound() مباشرة بعد أن يعيد جلب البيانات لا شيء، قبل عرض المكوّن الذي يفترض وجود السجل.

لماذا تُستبدل رسائل أخطاء الخادم بـ digest في الإنتاج؟

يحذف Next.js عمدًا نص الرسالة والتتبع من الأخطاء المرمية على الخادم في الإنتاج ويستبدلها بخاصية digest — وهي ترميز مُولَّد تلقائيًا — حتى لا يتسرب أي تفصيل داخلي أو سر إلى المتصفح. ويُسجَّل الخطأ الكامل على الخادم، وتتيح لك خاصية digest مطابقة بلاغ المستخدم بذلك السجل.

في التطوير ما زلت ترى الرسالة والتتبع الحقيقيين. والنتيجة العملية أن error.message لخطأ خادم داخل error.tsx في الإنتاج يكون عامًا، لذا نبني الربط والتقارير حول error.digest.

كيف نتعافى دون إعادة تحميل، وماذا عن أخطاء معالجات الأحداث؟

استدعِ خاصية reset() للتعافي دون إعادة تحميل كامل للصفحة؛ فهي تطلب من React إعادة عرض محتوى الحدود بإعادة محاولة المقطع الذي فشل. وإن كان السبب عابرًا — جلب متذبذب نجح الآن — يعود المقطع دون تنقّل.

أما الأخطاء التي لا يراها error.tsx إطلاقًا، أي المرمية في معالجات الأحداث والدوال غير المتزامنة، فنلتقطها في try/catch ونقود الواجهة بالحالة عارضين تنبيهًا مضمّنًا. وللأعطال المتوقعة في Server Action مثل خطأ تحقق أو بريد مكرر، نعيد قيمة خطأ ذات نوع بدل رمي استثناء، فيعرض النموذج الرسالة مضمّنة دون تفعيل أي حدود خطأ.

ملفات أخطاء App Router في لمحة

يلتقط error.tsx أخطاء العرض في مقطعه وأبنائه المتداخلين، ويجب أن يكون مكوّن عميل، ولا يلتقط تخطيطه الخاص، ويستقبل error و reset.

يلتقط global-error.tsx أخطاء التخطيط أو القالب الجذري، ويجب أن يكون مكوّن عميل، ويستبدل التخطيط الجذري فيلزمه عرض html و body، ويعمل في الإنتاج فقط.

يلتقط not-found.tsx استدعاءات notFound() والمسارات غير المطابقة، ولا يلزمه أن يكون مكوّن عميل، ويعيد HTTP 404، ولا تُفعّله الانهيارات الحقيقية.

الأخطاء المرمية في معالجات الأحداث أو الدوال غير المتزامنة لا يلتقطها أي من هذه الملفات؛ عالجها بـ try/catch وأظهرها بالحالة.

الأسئلة الشائعة

س: هل يلتقط error.tsx الأخطاء في layout.tsx الخاص به؟

ج: لا. يُعرض التخطيط فوق الحدود التي يعرّفها error.tsx. لالتقاط خطأ يرميه تخطيط مقطع، ضع error.tsx في المقطع الأب.

س: لماذا لا يظهر error.tsx في بيئة التطوير؟

ج: يعرض Next.js واجهة أخطاء التطوير فوق حدودك، ولا يتولى global-error.tsx العمل إلا في بناء إنتاج. شغّل بناء إنتاج لترى واجهة الخطأ الحقيقية.

س: هل تلتقط حدود الخطأ الأخطاء في معالجات onClick؟

ج: لا. تلتقط حدود الخطأ في React فقط الأخطاء المرمية أثناء العرض. غلّف منطق معالجات الأحداث وغير المتزامن بـ try/catch وأظهر الفشل بحالة المكوّن.

س: ما خاصية digest على كائن الخطأ؟

ج: ترميز يولّده Next.js لأخطاء الخادم في الإنتاج، ليستبدل الرسالة الحقيقية فلا يتسرب شيء إلى العميل. طابقه مع سجلات خادمك لإيجاد الخطأ الأساسي.

س: هل استدعاء notFound() يفعّل error.tsx؟

ج: لا. يرمي notFound() إشارة تحكم مخصصة تلتقطها أقرب not-found.tsx ويعيد 404. أما error.tsx فهو للاستثناءات غير المتوقعة فقط.