Skip to content

عیب‌یابی: گردش کار

"Workflow not found or not accessible"

گردش کار وجود دارد اما در سطح طبقه‌بندی بالاتر از taint فعلی نشست شما ذخیره شده است.

گردش کارهایی که در طول نشست CONFIDENTIAL ذخیره شده‌اند برای نشست‌های PUBLIC یا INTERNAL قابل مشاهده نیستند. مخزن از بررسی‌های canFlowTo در هر بارگذاری استفاده می‌کند و null برمی‌گرداند (به صورت "not found" نمایش داده می‌شود) وقتی طبقه‌بندی گردش کار از 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 به فضای خالی حساس است. از فاصله‌ها استفاده کنید، نه tab. هر سطح تودرتو باید دقیقاً ۲ فاصله باشد.

yaml
# اشتباه — tab یا تورفتگی ناسازگار
do:
- fetch:
      call: http

# درست
do:
  - fetch:
      call: http

عدم وجود نقل‌قول دور عبارات. رشته‌های عبارت با ${ } باید نقل‌قول داشته باشند، در غیر این صورت YAML { را به عنوان نگاشت درون‌خطی تفسیر می‌کند.

yaml
# اشتباه — خطای تجزیه YAML
endpoint: ${ .config.url }

# درست
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
# اشتباه — نقطه ابتدایی ندارد
value: "${ result.name }"

# درست
value: "${ .result.name }"

"undefined" در خروجی

dot-path به چیزی تفکیک نشد. دلایل رایج:

  • نام وظیفه اشتباه. هر وظیفه نتیجه خود را زیر نام خودش ذخیره می‌کند. اگر وظیفه شما fetch_data نام دارد، به نتیجه آن به عنوان ${ .fetch_data } ارجاع دهید، نه ${ .data } یا ${ .result }.
  • تودرتویی اشتباه. اگر فراخوانی HTTP {"data": {"items": [...]}} برگرداند، آیتم‌ها در ${ .fetch_data.data.items } هستند.
  • اندیس‌گذاری آرایه. از نحو براکت استفاده کنید: ${ .items[0].name }. مسیرهای فقط‌نقطه‌ای از اندیس‌های عددی پشتیبانی نمی‌کنند.

شرایط بولی کار نمی‌کنند

مقایسات عبارت سختگیرانه (===) هستند. مطمئن شوید نوع‌ها مطابقت دارند:

yaml
# اگر .count رشته "0" باشد شکست می‌خورد
if: "${ .count == 0 }"

# وقتی .count عدد باشد کار می‌کند
if: "${ .count == 0 }"

بررسی کنید آیا وظایف بالادستی رشته یا عدد برمی‌گردانند. پاسخ‌های HTTP اغلب مقادیر رشته‌ای برمی‌گردانند که برای مقایسه نیاز به تبدیل ندارند -- فقط با فرم رشته‌ای مقایسه کنید.


مشکلات فراخوانی HTTP

Timeout

فراخوانی‌های HTTP از ابزار web_fetch عبور می‌کنند. اگر سرور هدف کند باشد، درخواست ممکن است منقضی شود. هیچ override timeout برای هر وظیفه برای فراخوانی‌های HTTP در workflow DSL وجود ندارد -- timeout پیش‌فرض ابزار 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"

زیرگردش کارها تا ۵ سطح عمق می‌توانند تودرتو شوند. این محدودیت از بازگشت بی‌نهایت جلوگیری می‌کند وقتی گردش کار A گردش کار B را فراخوانی کند و گردش کار B گردش کار A را فراخوانی کند.

راه‌حل:

  • زنجیره گردش کار را تخت کنید. مراحل را در گردش کارهای کمتری ترکیب کنید.
  • ارجاعات دوری را بررسی کنید که دو گردش کار یکدیگر را فراخوانی می‌کنند.

اجرای Shell غیرفعال

"Shell execution failed" یا نتیجه خالی از وظایف run

پرچم allowShellExecution در زمینه ابزار گردش کار کنترل می‌کند آیا وظایف run با اهداف shell یا script مجاز هستند. وقتی غیرفعال باشد، این وظایف شکست می‌خورند.

راه‌حل: بررسی کنید آیا اجرای shell در پیکربندی Triggerfish شما فعال است. در محیط‌های تولید، اجرای shell ممکن است عمداً برای امنیت غیرفعال شده باشد.


گردش کار اجرا می‌شود اما خروجی اشتباه تولید می‌کند

اشکال‌زدایی با 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 به جای "permission denied" "not found" گزارش می‌دهد.

این عمدی است -- وجود گردش کارهای طبقه‌بندی‌شده به نشست‌های با طبقه‌بندی پایین‌تر فاش نمی‌شود.

راه‌حل: 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 تغییر دهند.


عامل درمان‌گر ایجاد نمی‌شود

گردش کار اجرا می‌شود اما عامل درمان‌گر ظاهر نمی‌شود. بررسی کنید:

  1. enabled روی true باشد در metadata.triggerfish.self_healing.
  2. پیکربندی در مکان صحیح باشد — باید زیر metadata.triggerfish.self_healing تودرتو باشد، نه در سطح بالا.
  3. همه مراحل فراداده داشته باشند — اگر اعتبارسنجی در زمان ذخیره شکست بخورد، گردش کار بدون فعال بودن خوددرمانی ذخیره شده است.

اصلاحات پیشنهادی در وضعیت انتظار مانده‌اند

اگر approval_required روی true باشد (پیش‌فرض)، نسخه‌های پیشنهادی منتظر بررسی انسانی می‌مانند. از workflow_version_list برای مشاهده پیشنهادهای معلق و workflow_version_approve یا workflow_version_reject برای اقدام روی آنها استفاده کنید.


"Retry budget exhausted" / تشدید غیرقابل حل

عامل درمان‌گر تمام تلاش‌های مداخله خود (پیش‌فرض ۳) را بدون حل مشکل مصرف کرده است. به عنوان unresolvable تشدید می‌کند و تلاش برای اصلاح را متوقف می‌کند.

راه‌حل:

  • workflow_healing_status را بررسی کنید تا ببینید چه مداخلاتی تلاش شده‌اند.
  • مشکل زیربنایی را به صورت دستی بررسی و اصلاح کنید.
  • برای اجازه تلاش‌های بیشتر، retry_budget را در پیکربندی خوددرمانی افزایش دهید و گردش کار را دوباره ذخیره کنید.