N8n: عقدة التبديل توجه صامتة إلى false عند مقارنة قيمة منطقية — "نوع خاطئ: 'true ' عبارة عن نص لكن كان متوقعاً نوعاً منطقياً"

أنشر هذا لأنه استغرق مني بضع ساعات وفشل بصمت، وهذا أسوأ مزيج. إذا كنت توجه أي شيء مهم عبر عقدة IF أو Switch على قيمة منطقية، فهذا يستحق عشر دقائق من وقتك.

هناك عدة مشاكل مفتوحة وخيوط منتدى تصف هذا السلوك بدون سبب جذري مرفق. هذا ما وجدته.

الأعراض

كان لدي عقدة Switch تقرر ما إذا كان سيتم إرسال تنبيه. كان مخرج العقدة العلوية يبدو هكذا:

{ “shouldEscalate”: true }

شرط Switch: القيمة:

{{ $(‘Extract Response’).first().json.shouldEscalate }}
المشغل: Boolean → is true
تم توجيه كل عملية تنفيذ إلى false. لا خطأ. تم الإبلاغ عن نجاح التنفيذ. التنبيه لم ينطلق أبداً.

ما لم يكن

أضعت وقتاً في الفرضيات الخاطئة أولاً، إذاً إليها لتوفير عليك الرحلة:

•	ليس .first() مقابل .item — تحققت
•	ليست مشكلة multi-run/item-lineage
•	ليست العقدة العلوية التي تنتج القيمة الخاطئة

أثبتت الأخيرة بإسقاط عقدة Set مباشرة قبل Switch التي أطلقت القيمة الخام بالإضافة إلى نوعها: { “val”: true, “type”: “boolean”, “runs”: 1 }
قيمة منطقية حقيقية. تشغيل واحد. القيمة الصحيحة تصل إلى العقدة. وحتى الآن أرسل Switch القيمة false.

السبب الفعلي

يعرض n8n مخرج تعبير {{ }} كنص. إذاً تصل قيمة منطقية حقيقية true إلى المشغل كسلسلة نصية “true” — وإذا كان هناك أي مسافة بيضاء زائدة أو سطر جديد في حقل المعامل بعد الإغلاق }} (من السهل جداً إدخاله عند اللصق)، تحصل على "true ".

مشغل Boolean الصارم يحصل على "true "، وهو ليس قيمة منطقية، وتفشل المقارنة. بصمت، في اتجاه false.

في النهاية أظهرت العقدة ذلك حرفياً: Wrong type: 'true ’ is a string but was expecting a boolean

لماذا لم تعمل الإصلاحات الواضحة

حاولت التحويل داخل التعبير:
{{ String($(‘Extract Response’).first().json.shouldEscalate).trim().toBoolean() }}

فشل بالفعل. المسافة البيضاء ليست داخل التعبير — يتم إدخالها بعد }} أثناء عرض n8n الخاص به. لا شيء تفعله داخل الأقواس يمكنه الوصول إليها.

تبديل “Convert types where required” يغير وضع الفشل بدلاً من إصلاحه. في حالتي، إحدى الإعدادات وجهت كل شيء إلى true والآخر وجه كل شيء إلى false. كلاهما خاطئ؛ أحدهما فقط أكثر صراخاً.

الإصلاح الذي ينجح
توقف عن مقارنة القيمة المنطقية. أطلق كلمة رئيسية صريحة ومطابقة على نص:
القيمة: {{ $(‘Extract Response’).first().json.shouldEscalate ? “ESCALATE” : “NORMAL” }}
المشغل: String → contains
مطابقة: ESCALATE
تحويل الأنواع: off

"ESCALATE " لا تزال تحتوي على “ESCALATE”. "NORMAL " لا تحتوي عليها بأي طريقة. تصبح المسافة البيضاء الزائدة غير ضارة بدلاً من أن تكون قاتلة.

تم التحقق من الاتجاهات في كلا الاتجاهين على نفس الإصدار — الشرط true يوجه true، والشرط false يوجه false. يستحق القيام بكليهما؛ الاختبار في اتجاه واحد فقط هو نصف اختبار، وهذا الخلل قادر بشكل خاص على النجاح في اتجاه واحد أثناء الفشل في الآخر.

الإصدار العام

إذا كانت عقدة Switch أو IF تتخذ قراراً يهم فعلاً — تنبيهات أو تصعيد أو بوابات الامتثال، أي شيء حيث يكون أخذ الفرع الخاطئ بصمت مكلفاً — لا توجهها على قيمة منطقية خام. أطلق سلسلة نصية حارسة ومطابقة عليها.

“وضع الفشل هنا ليس خطأ. إنها عملية تنفيذ خضراء فعلت الشيء الخاطئ.”

تصحيح الأخطاء في هذا أمر صعب جداً لأنه يفشل بصمت ويظهر أخضر. مسارات السبب الجذري لديك: يتم تحويل القيمة إلى نص بواسطة محرك التعبيرات، وأي مسافة بيضاء ضالة بعد }} تكسر عوامل النوع الصارمة. قص الفراغات داخل الأقواس لن يصلح المشكلة، لأن المسافة البيضاء تظهر بعد العرض، وليس قبله.

حل sentinel-string الخاص بك هو الخيار الصحيح، إنها الطريقة الأكثر قوة للتوجيه على قيمة منطقية بمجرد تمريرها عبر تعبير. شيء واحد يستحق الإضافة: يمكنك أيضاً محاولة فرض النوع على عقدة Set في المنطقة العليا (باستخدام محدد النوع، وليس التعبير فقط) قبل Switch، فإن ذلك يتم التوجيه أحياناً عبر مسار الإكراه الداخلي في n8n بدلاً من مسار عرض النص. لا يضمن تجنبه في كل إصدار، لكنه رخيص الاختبار.

ملاحظة جيدة، هذا هو نوع الخطأ الذي يكلف أكثر بكثير من الدقائق العشر التي تطلب من الناس قضاءها.

مرحبا @Tonylw14 أهلا وسهلا!
الإكراه ليس غير مشروط، فهو يحدث فقط عندما يكون التعبير داخل سلسلة نصية. حقل يحتوي على لا شيء سوى {{ ... }} يعيد القيمة الأصلية، ومسافة واحدة بعد }} تحول الحقل إلى قالب سلسلة نصية، وهو مصدر "true ". يعمل التوجيه المنطقي بمجرد أن يحتوي الحقل على التعبير وحده.
انقر على حقل القيمة، وحدد الكل، وأعد كتابة التعبير، ولا تترك مسافة أو فاصل أسطر بعد }}. للتحقق، انسخ عقدة Switch والصقها في محرر نصوص: يجب أن تقرأ المعاملة ={{ $('Extract Response').first().json.shouldEscalate }} وتنتهي عند الأقواس المغلقة.
أكدت n8n أن هذا السلوك مقصود، حيث يتم إكراه التعبير المضمن في سلسلة نصية إلى سلسلة نصية حتى عندما تكون السلسلة المحيطة مسافة بيضاء فقط:

إضافة صغيرة لأي شخص يواجه هذه المشكلة، فهي تؤثر أكثر عندما تنسخ والصق التعبيرات من Slack أو المستندات أو ChatGPT، لأنها تدرج مسافة زائدة أو مسافة غير منفصلة تكاد تكون غير مرئية. إذا فشل المسار المنطقي بصمت، كما يقول Anshul، فإن كتابة التعبير يدويًا أسرع بكثير من محاولة العثور على المسافة البيضاء بالنظر إلى التعبير.

@Anshul_Namdev @ShawnWilliams — شكراً لكما. هذه آلية أكثر دقة مما كتبت، وهي الجزء الذي أخطأت فيه. قلت إن الإكراه كان غير مشروط؛ لكنه ليس كذلك. الحقل الذي يحتوي فقط على التعبير يعيد القيمة الأصلية، وأي شيء آخر — بما في ذلك مسافة زائدة واحدة — يجعله قالب نص، وهو ما أنتج 'true. هذا يشرح أيضاً لماذا لم يفعل القص داخل الأقواس أي شيء: يحدث الإكراه عندما يتم عرض القالب، بعد أن تم تقييم التعبير بالفعل.

@ShawnWilliams هذا بالضبط. لقد لصقت هذه التعبيرات من دردشة أثناء البناء. سأعيد الكتابة بيدي من الآن فصاعداً.

تحديث المنشور بالآلية المصححة وارتباط المشكلة.

Salman_Mehboob فكرة جيدة بفرض النوع على عقدة Set في اتجاه مجرى النهر. لم أحاول هذا المسار، سأختبره وأبلغ عن النتائج.

أنا أحتفظ بسلسلة الحارس على التوجيه الحساس للسلامة، لسبب متعلق بنمط الفشل بدلاً من الآلية: المسافة الزائدة غير المرئية لا تكون مرئية في واجهة المستخدم، وإذا أعيد إدخالها لاحقاً، فإن الفرع يفشل بصمت على تنفيذ أخضر. المطابقة التي تحتوي على كلمة رئيسية صريحة محصنة ضد هذه الفئة بأكملها. لكن الحقل النظيف هو الإصلاح الفعلي ويجب أن يأتي أولاً.