استكشاف الأخطاء: سير العمل
"Workflow not found or not accessible"
سير العمل موجود لكنه مخزن عند مستوى تصنيف أعلى من taint جلستك الحالية.
سير العمل المحفوظ أثناء جلسة CONFIDENTIAL غير مرئي لجلسات PUBLIC أو INTERNAL. يستخدم المخزن فحوصات canFlowTo عند كل تحميل، ويُرجع null (يظهر كـ "غير موجود") عندما يتجاوز تصنيف سير العمل taint الجلسة.
الحل: قم بتصعيد taint جلستك بالوصول إلى بيانات مصنفة أولاً، أو أعد حفظ سير العمل من جلسة ذات تصنيف أقل إذا سمحت المحتويات بذلك.
التحقق: شغّل workflow_list لمعرفة أي سير عمل مرئي عند مستوى تصنيفك الحالي. إذا كان سير العمل المتوقع مفقوداً، فقد تم حفظه عند مستوى أعلى.
"Workflow classification ceiling breached"
تجاوز مستوى taint الجلسة classification_ceiling الخاص بسير العمل. يتم تشغيل هذا الفحص قبل كل مهمة، لذا يمكن أن يُثار أثناء التنفيذ إذا قامت مهمة سابقة بتصعيد taint الجلسة.
على سبيل المثال، سير عمل بـ classification_ceiling: INTERNAL سيتوقف إذا استرجع استدعاء triggerfish:memory بيانات CONFIDENTIAL تصعّد taint الجلسة.
الحل:
- ارفع
classification_ceilingالخاص بسير العمل ليتطابق مع حساسية البيانات المتوقعة. - أو أعد هيكلة سير العمل بحيث لا يتم الوصول إلى بيانات مصنفة. استخدم معاملات الإدخال بدلاً من قراءة الذاكرة المصنفة.
أخطاء تحليل YAML
"YAML parse error: ..."
أخطاء شائعة في صيغة YAML:
المسافة البادئة. YAML حساس للمسافات البيضاء. استخدم المسافات وليس علامات التبويب. كل مستوى تداخل يجب أن يكون بالضبط مسافتين.
yaml
# Wrong — tabs or inconsistent indent
do:
- fetch:
call: http
# Correct
do:
- fetch:
call: httpعلامات اقتباس مفقودة حول التعبيرات. سلاسل التعبيرات التي تحتوي على ${ } يجب أن تكون بين علامات اقتباس، وإلا يفسر YAML { كتعيين مضمّن.
yaml
# Wrong — YAML parse error
endpoint: ${ .config.url }
# Correct
endpoint: "${ .config.url }"كتلة document مفقودة. كل سير عمل يجب أن يحتوي على حقل document مع dsl و namespace و name:
yaml
document:
dsl: "1.0"
namespace: my-workflows
name: my-workflow"Workflow YAML must be an object"
تم تحليل YAML بنجاح لكن النتيجة قيمة عددية أو مصفوفة وليست كائناً. تحقق أن YAML الخاص بك يحتوي على مفاتيح المستوى الأعلى (document، do).
"Task has no recognized type"
يجب أن يحتوي كل إدخال مهمة على مفتاح نوع واحد بالضبط: call، run، set، switch، for، raise، emit، أو wait. إذا لم يجد المحلل أياً من هذه المفاتيح، يبلغ عن نوع غير معروف.
السبب الشائع: خطأ مطبعي في اسم نوع المهمة (مثل calls بدلاً من call).
فشل تقييم التعبيرات
قيم خاطئة أو فارغة
التعبيرات تستخدم صيغة ${ .path.to.value }. النقطة البادئة مطلوبة — فهي تثبت المسار في جذر سياق بيانات سير العمل.
yaml
# Wrong — missing leading dot
value: "${ result.name }"
# Correct
value: "${ .result.name }""undefined" في المخرجات
لم يحل المسار النقطي إلى شيء. الأسباب الشائعة:
- اسم مهمة خاطئ. كل مهمة تخزن نتيجتها تحت اسمها. إذا كان اسم مهمتك
fetch_data، اشر إلى نتيجتها بـ${ .fetch_data }، وليس${ .data }أو${ .result }. - تداخل خاطئ. إذا أرجع استدعاء HTTP
{"data": {"items": [...]}}فإن العناصر في${ .fetch_data.data.items }. - فهرسة المصفوفة. استخدم صيغة الأقواس:
${ .items[0].name }. المسارات بالنقاط فقط لا تدعم الفهارس الرقمية.
الشروط المنطقية لا تعمل
مقارنات التعبيرات صارمة (===). تأكد من تطابق الأنواع:
yaml
# This fails if .count is a string "0"
if: "${ .count == 0 }"
# Works when .count is a number
if: "${ .count == 0 }"تحقق مما إذا كانت المهام السابقة تُرجع سلاسل أو أرقام. غالباً ما تُرجع استجابات HTTP قيم سلسلة لا تحتاج إلى تحويل للمقارنة — فقط قارن مع الشكل النصي.
فشل استدعاءات HTTP
المهلة الزمنية
تمر استدعاءات HTTP عبر أداة web_fetch. إذا كان الخادم الهدف بطيئاً، فقد تنتهي مهلة الطلب. لا يوجد تجاوز مهلة لكل مهمة لاستدعاءات HTTP في DSL سير العمل — يتم تطبيق المهلة الافتراضية لأداة web_fetch.
حظر SSRF
جميع طلبات HTTP الصادرة في Triggerfish تحل DNS أولاً وتتحقق من IP المحلول مقابل قائمة رفض مضمّنة. نطاقات IP الخاصة والمحجوزة محظورة دائماً.
إذا كان سير عملك يستدعي خدمة داخلية على IP خاص (مثل http://192.168.1.100/api)، سيتم حظره بواسطة منع SSRF. هذا مقصود ولا يمكن تكوينه.
الحل: استخدم اسم مضيف عام يحل إلى IP عام، أو استخدم triggerfish:mcp للتوجيه عبر خادم MCP لديه وصول مباشر.
رؤوس مفقودة
يربط نوع استدعاء http with.headers مباشرة برؤوس الطلب. إذا كان API الخاص بك يتطلب مصادقة، أضف الرأس:
yaml
- fetch:
call: http
with:
endpoint: "https://api.example.com/data"
headers:
Authorization: "Bearer ${ .api_token }"تأكد أن قيمة الرمز المميز مقدمة في مدخلات سير العمل أو تم تعيينها بواسطة مهمة سابقة.
حد تكرار سير العمل الفرعي
"Workflow recursion depth exceeded maximum of 5"
يمكن لسير العمل الفرعية التداخل حتى 5 مستويات عمقاً. يمنع هذا الحد التكرار اللانهائي عندما يستدعي سير العمل A سير العمل B الذي يستدعي سير العمل A.
الحل:
- قم بتسطيح سلسلة سير العمل. ادمج الخطوات في عدد أقل من سير العمل.
- تحقق من المراجع الدائرية حيث يستدعي سيرا عمل بعضهما البعض.
تنفيذ الصدفة معطل
"Shell execution failed" أو نتيجة فارغة من مهام run
تتحكم علامة allowShellExecution في سياق أداة سير العمل فيما إذا كانت مهام run ذات أهداف shell أو script مسموحة. عند التعطيل، تفشل هذه المهام.
الحل: تحقق مما إذا كان تنفيذ الصدفة ممكّناً في إعدادات Triggerfish الخاصة بك. في بيئات الإنتاج، قد يكون تنفيذ الصدفة معطلاً عمداً لأسباب أمنية.
سير العمل يعمل لكن ينتج مخرجات خاطئة
التصحيح باستخدام workflow_history
استخدم workflow_history لفحص عمليات التشغيل السابقة:
workflow_history with workflow_name: "my-workflow" and limit: "5"كل إدخال في السجل يتضمن:
- status —
completedأوfailed - error — رسالة الخطأ إذا فشل
- taskCount — عدد المهام في سير العمل
- startedAt / completedAt — معلومات التوقيت
التحقق من تدفق السياق
كل مهمة تخزن نتيجتها في سياق البيانات تحت اسم المهمة. إذا كان سير عملك يحتوي على مهام باسم fetch و transform و save، فإن سياق البيانات بعد المهام الثلاث يبدو هكذا:
json
{
"fetch": { "...http response..." },
"transform": { "...transformed data..." },
"save": { "...save result..." }
}الأخطاء الشائعة:
- الكتابة فوق السياق. مهمة
setتعيّن لمفتاح موجود بالفعل ستستبدل القيمة السابقة. - مرجع مهمة خاطئ. الإشارة إلى
${ .step1 }عندما يكون اسم المهمةstep_1. - تحويل الإدخال يستبدل السياق. توجيه
input.fromيستبدل سياق إدخال المهمة بالكامل. إذا استخدمتinput.from: "${ .config }"فإن المهمة ترى فقط كائنconfigوليس السياق الكامل.
مخرجات مفقودة
إذا اكتمل سير العمل لكنه أرجع مخرجات فارغة، تحقق مما إذا كانت نتيجة المهمة الأخيرة هي ما تتوقعه. مخرجات سير العمل هي سياق البيانات الكامل عند الاكتمال، مع تصفية المفاتيح الداخلية.
"Permission denied" عند workflow_delete
تقوم أداة workflow_delete بتحميل سير العمل أولاً باستخدام مستوى taint الجلسة الحالية. إذا تم حفظ سير العمل عند مستوى تصنيف يتجاوز taint جلستك، يُرجع التحميل null وتبلغ workflow_delete عن "not found" بدلاً من "permission denied".
هذا مقصود — لا يتم الكشف عن وجود سير عمل مصنفة لجلسات ذات تصنيف أقل.
الحل: قم بتصعيد taint جلستك ليتطابق مع أو يتجاوز مستوى تصنيف سير العمل قبل حذفه. أو احذفه من نفس نوع الجلسة حيث تم حفظه في الأصل.
الإصلاح الذاتي
"Step metadata missing on task 'X': self-healing requires description, expects, produces"
عندما يكون self_healing.enabled مضبوطاً على true، يجب أن تحتوي كل مهمة على جميع حقول البيانات الوصفية الثلاثة. يرفض المحلل سير العمل عند الحفظ إذا كانت أي منها مفقودة.
الحل: أضف description و expects و produces إلى كتلة metadata لكل مهمة:
yaml
- my-task:
call: http
with:
endpoint: "https://example.com/api"
metadata:
description: "What this step does and why"
expects: "What this step needs as input"
produces: "What this step outputs""Self-healing config mutation rejected in version proposal"
اقترح وكيل الإصلاح إصداراً جديداً من سير العمل يعدّل كتلة تكوين self_healing. هذا محظور — لا يمكن للوكيل تغيير تكوين الإصلاح الخاص به.
هذا يعمل كما هو مصمم. يمكن للبشر فقط تعديل تكوين self_healing عن طريق حفظ إصدار جديد من سير العمل مباشرة عبر workflow_save.
وكيل الإصلاح لا يظهر
سير العمل يعمل لكن لا يظهر وكيل إصلاح. تحقق من:
enabledمضبوط علىtrueفيmetadata.triggerfish.self_healing.- التكوين في الموقع الصحيح — يجب أن يكون متداخلاً تحت
metadata.triggerfish.self_healing، وليس في المستوى الأعلى. - جميع الخطوات لديها بيانات وصفية — إذا فشل التحقق عند الحفظ، فقد تم حفظ سير العمل بدون تمكين الإصلاح الذاتي.
الإصلاحات المقترحة عالقة في حالة الانتظار
إذا كان approval_required مضبوطاً على true (الافتراضي)، تنتظر الإصدارات المقترحة المراجعة البشرية. استخدم workflow_version_list لعرض المقترحات المعلقة و workflow_version_approve أو workflow_version_reject للتصرف بشأنها.
"Retry budget exhausted" / تصعيد غير قابل للحل
استنفد وكيل الإصلاح جميع محاولات التدخل (الافتراضي 3) دون حل المشكلة. يصعّد كـ unresolvable ويتوقف عن محاولة الإصلاح.
الحل:
- تحقق من
workflow_healing_statusلمعرفة التدخلات التي تمت محاولتها. - راجع وأصلح المشكلة الأساسية يدوياً.
- للسماح بمزيد من المحاولات، قم بزيادة
retry_budgetفي تكوين الإصلاح الذاتي وأعد حفظ سير العمل.
