flowstudio-power-automate-debug

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Power Automate Debugging with FlowStudio MCP

使用FlowStudio MCP调试Power Automate

A step-by-step diagnostic process for investigating failing Power Automate cloud flows through the FlowStudio MCP server.
Prerequisite: A FlowStudio MCP server must be reachable with a valid JWT. See the
flowstudio-power-automate-mcp
skill for connection setup.
Subscribe at https://mcp.flowstudio.app

通过FlowStudio MCP服务器调查故障Power Automate云流的分步诊断流程。
前提条件:必须能通过有效的JWT访问FlowStudio MCP服务器。连接设置请参考
flowstudio-power-automate-mcp
技能。
订阅地址:https://mcp.flowstudio.app

Source of Truth

权威来源

Always call
tools/list
first
to confirm available tool names and their parameter schemas. Tool names and parameters may change between server versions. This skill covers response shapes, behavioral notes, and diagnostic patterns — things
tools/list
cannot tell you. If this document disagrees with
tools/list
or a real API response, the API wins.

**请始终先调用
tools/list
**以确认可用工具名称及其参数 schema。工具名称和参数可能会随服务器版本变化。 本技能涵盖响应格式、行为说明和诊断模式——这些是
tools/list
无法提供的信息。如果本文档与
tools/list
或实际API响应存在冲突,以API为准。

Python Helper

Python辅助工具

python
import json, urllib.request

MCP_URL   = "https://mcp.flowstudio.app/mcp"
MCP_TOKEN = "<YOUR_JWT_TOKEN>"

def mcp(tool, **kwargs):
    payload = json.dumps({"jsonrpc": "2.0", "id": 1, "method": "tools/call",
                          "params": {"name": tool, "arguments": kwargs}}).encode()
    req = urllib.request.Request(MCP_URL, data=payload,
        headers={"x-api-key": MCP_TOKEN, "Content-Type": "application/json",
                 "User-Agent": "FlowStudio-MCP/1.0"})
    try:
        resp = urllib.request.urlopen(req, timeout=120)
    except urllib.error.HTTPError as e:
        body = e.read().decode("utf-8", errors="replace")
        raise RuntimeError(f"MCP HTTP {e.code}: {body[:200]}") from e
    raw = json.loads(resp.read())
    if "error" in raw:
        raise RuntimeError(f"MCP error: {json.dumps(raw['error'])}")
    return json.loads(raw["result"]["content"][0]["text"])

ENV = "<environment-id>"   # e.g. Default-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

python
import json, urllib.request

MCP_URL   = "https://mcp.flowstudio.app/mcp"
MCP_TOKEN = "<YOUR_JWT_TOKEN>"

def mcp(tool, **kwargs):
    payload = json.dumps({"jsonrpc": "2.0", "id": 1, "method": "tools/call",
                          "params": {"name": tool, "arguments": kwargs}}).encode()
    req = urllib.request.Request(MCP_URL, data=payload,
        headers={"x-api-key": MCP_TOKEN, "Content-Type": "application/json",
                 "User-Agent": "FlowStudio-MCP/1.0"})
    try:
        resp = urllib.request.urlopen(req, timeout=120)
    except urllib.error.HTTPError as e:
        body = e.read().decode("utf-8", errors="replace")
        raise RuntimeError(f"MCP HTTP {e.code}: {body[:200]}") from e
    raw = json.loads(resp.read())
    if "error" in raw:
        raise RuntimeError(f"MCP error: {json.dumps(raw['error'])}")
    return json.loads(raw["result"]["content"][0]["text"])

ENV = "<environment-id>"   # 示例:Default-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

FlowStudio for Teams: Fast-Path Diagnosis (Skip Steps 2–4)

Teams版FlowStudio:快速诊断(跳过步骤2-4)

If you have a FlowStudio for Teams subscription,
get_store_flow_errors
returns per-run failure data including action names and remediation hints in a single call — no need to walk through live API steps.
python
undefined
如果你拥有Teams版FlowStudio订阅,
get_store_flow_errors
接口可一次性返回每个运行实例的故障数据,包括操作名称和修复提示——无需逐步调用实时API。
python
undefined

Quick failure summary

快速故障汇总

summary = mcp("get_store_flow_summary", environmentName=ENV, flowName=FLOW_ID)
summary = mcp("get_store_flow_summary", environmentName=ENV, flowName=FLOW_ID)

{"totalRuns": 100, "failRuns": 10, "failRate": 0.1,

{"totalRuns": 100, "failRuns": 10, "failRate": 0.1,

"averageDurationSeconds": 29.4, "maxDurationSeconds": 158.9,

"averageDurationSeconds": 29.4, "maxDurationSeconds": 158.9,

"firstFailRunRemediation": "<hint or null>"}

"firstFailRunRemediation": "<提示内容或null>"}

print(f"Fail rate: {summary['failRate']:.0%} over {summary['totalRuns']} runs")
print(f"故障占比:{summary['failRate']:.0%}(共{summary['totalRuns']}次运行)")

Per-run error details (requires active monitoring to be configured)

单运行实例错误详情(需配置主动监控)

errors = mcp("get_store_flow_errors", environmentName=ENV, flowName=FLOW_ID) if errors: for r in errors[:3]: print(r["startTime"], "|", r.get("failedActions"), "|", r.get("remediationHint")) # If errors confirms the failing action → jump to Step 6 (apply fix) else: # Store doesn't have run-level detail for this flow — use live tools (Steps 2–5) pass

For the full governance record (description, complexity, tier, connector list):
```python
record = mcp("get_store_flow", environmentName=ENV, flowName=FLOW_ID)
errors = mcp("get_store_flow_errors", environmentName=ENV, flowName=FLOW_ID) if errors: for r in errors[:3]: print(r["startTime"], "|", r.get("failedActions"), "|", r.get("remediationHint")) # 如果errors确认了故障操作 → 跳至步骤6(应用修复) else: # 存储中没有此流的运行实例详情 → 使用实时工具(步骤2-5) pass

如需完整治理记录(描述、复杂度、层级、连接器列表):
```python
record = mcp("get_store_flow", environmentName=ENV, flowName=FLOW_ID)

{"displayName": "My Flow", "state": "Started",

{"displayName": "My Flow", "state": "Started",

"runPeriodTotal": 100, "runPeriodFailRate": 0.1, "runPeriodFails": 10,

"runPeriodTotal": 100, "runPeriodFailRate": 0.1, "runPeriodFails": 10,

"runPeriodDurationAverage": 29410.8, ← milliseconds

"runPeriodDurationAverage": 29410.8, ← 毫秒

"runError": "{"code": "EACCES", ...}", ← JSON string, parse it

"runError": "{"code": "EACCES", ...}", ← JSON字符串,需解析

"description": "...", "tier": "Premium", "complexity": "{...}"}

"description": "...", "tier": "Premium", "complexity": "{...}"}

if record.get("runError"): last_err = json.loads(record["runError"]) print("Last run error:", last_err)

---
if record.get("runError"): last_err = json.loads(record["runError"]) print("上次运行错误:", last_err)

---

Step 1 — Locate the Flow

步骤1 — 定位目标流

python
result = mcp("list_live_flows", environmentName=ENV)
python
result = mcp("list_live_flows", environmentName=ENV)

Returns a wrapper object: {mode, flows, totalCount, error}

返回包装对象:{mode, flows, totalCount, error}

target = next(f for f in result["flows"] if "My Flow Name" in f["displayName"]) FLOW_ID = target["id"] # plain UUID — use directly as flowName print(FLOW_ID)

---
target = next(f for f in result["flows"] if "My Flow Name" in f["displayName"]) FLOW_ID = target["id"] # 纯UUID — 直接作为flowName使用 print(FLOW_ID)

---

Step 2 — Find the Failing Run

步骤2 — 查找故障运行实例

python
runs = mcp("get_live_flow_runs", environmentName=ENV, flowName=FLOW_ID, top=5)
python
runs = mcp("get_live_flow_runs", environmentName=ENV, flowName=FLOW_ID, top=5)

Returns direct array (newest first):

返回直接数组(按时间倒序):

[{"name": "08584296068667933411438594643CU15",

[{"name": "08584296068667933411438594643CU15",

"status": "Failed",

"status": "Failed",

"startTime": "2026-02-25T06:13:38.6910688Z",

"startTime": "2026-02-25T06:13:38.6910688Z",

"endTime": "2026-02-25T06:15:24.1995008Z",

"endTime": "2026-02-25T06:15:24.1995008Z",

"triggerName": "manual",

"triggerName": "manual",

"error": {"code": "ActionFailed", "message": "An action failed..."}},

"error": {"code": "ActionFailed", "message": "An action failed..."}},

{"name": "...", "status": "Succeeded", "error": null, ...}]

{"name": "...", "status": "Succeeded", "error": null, ...}]

for r in runs: print(r["name"], r["status"], r["startTime"])
RUN_ID = next(r["name"] for r in runs if r["status"] == "Failed")

---
for r in runs: print(r["name"], r["status"], r["startTime"])
RUN_ID = next(r["name"] for r in runs if r["status"] == "Failed")

---

Step 3 — Get the Top-Level Error

步骤3 — 获取顶层错误信息

python
err = mcp("get_live_flow_run_error",
    environmentName=ENV, flowName=FLOW_ID, runName=RUN_ID)
python
err = mcp("get_live_flow_run_error",
    environmentName=ENV, flowName=FLOW_ID, runName=RUN_ID)

Returns:

返回:

{

{

"runName": "08584296068667933411438594643CU15",

"runName": "08584296068667933411438594643CU15",

"failedActions": [

"failedActions": [

{"actionName": "Apply_to_each_prepare_workers", "status": "Failed",

{"actionName": "Apply_to_each_prepare_workers", "status": "Failed",

"error": {"code": "ActionFailed", "message": "An action failed..."},

"error": {"code": "ActionFailed", "message": "An action failed..."},

"startTime": "...", "endTime": "..."},

"startTime": "...", "endTime": "..."},

{"actionName": "HTTP_find_AD_User_by_Name", "status": "Failed",

{"actionName": "HTTP_find_AD_User_by_Name", "status": "Failed",

"code": "NotSpecified", "startTime": "...", "endTime": "..."}

"code": "NotSpecified", "startTime": "...", "endTime": "..."}

],

],

"allActions": [

"allActions": [

{"actionName": "Apply_to_each", "status": "Skipped"},

{"actionName": "Apply_to_each", "status": "Skipped"},

{"actionName": "Compose_WeekEnd", "status": "Succeeded"},

{"actionName": "Compose_WeekEnd", "status": "Succeeded"},

...

...

]

]

}

}

failedActions is ordered outer-to-inner. The ROOT cause is the LAST entry:

failedActions按从外到内的顺序排列。根本原因是最后一个条目:

root = err["failedActions"][-1] print(f"Root action: {root['actionName']} → code: {root.get('code')}")
root = err["failedActions"][-1] print(f"根源操作:{root['actionName']} → 错误码:{root.get('code')}")

allActions shows every action's status — useful for spotting what was Skipped

allActions展示所有操作的状态 — 有助于发现被跳过的操作

See common-errors.md to decode the error code.

请参考common-errors.md解析错误码。


---

---

Step 4 — Read the Flow Definition

步骤4 — 读取流定义

python
defn = mcp("get_live_flow", environmentName=ENV, flowName=FLOW_ID)
actions = defn["properties"]["definition"]["actions"]
print(list(actions.keys()))
Find the failing action in the definition. Inspect its
inputs
expression to understand what data it expects.

python
defn = mcp("get_live_flow", environmentName=ENV, flowName=FLOW_ID)
actions = defn["properties"]["definition"]["actions"]
print(list(actions.keys()))
在定义中找到故障操作,检查其
inputs
表达式以了解它期望的数据格式。

Step 5 — Inspect Action Outputs (Walk Back from Failure)

步骤5 — 检查操作输出(从故障点回溯)

For each action leading up to the failure, inspect its runtime output:
python
for action_name in ["Compose_WeekEnd", "HTTP_Get_Data", "Parse_JSON"]:
    result = mcp("get_live_flow_run_action_outputs",
        environmentName=ENV,
        flowName=FLOW_ID,
        runName=RUN_ID,
        actionName=action_name)
    # Returns an array — single-element when actionName is provided
    out = result[0] if result else {}
    print(action_name, out.get("status"))
    print(json.dumps(out.get("outputs", {}), indent=2)[:500])
⚠️ Output payloads from array-processing actions can be very large. Always slice (e.g.
[:500]
) before printing.

对于故障发生前的每个操作,检查其运行时输出:
python
for action_name in ["Compose_WeekEnd", "HTTP_Get_Data", "Parse_JSON"]:
    result = mcp("get_live_flow_run_action_outputs",
        environmentName=ENV,
        flowName=FLOW_ID,
        runName=RUN_ID,
        actionName=action_name)
    # 返回数组 — 指定actionName时为单元素数组
    out = result[0] if result else {}
    print(action_name, out.get("status"))
    print(json.dumps(out.get("outputs", {}), indent=2)[:500])
⚠️ 数组处理操作的输出 payload 可能非常大。 打印前务必进行切片(例如
[:500]
)。

Step 6 — Pinpoint the Root Cause

步骤6 — 定位根本原因

Expression Errors (e.g.
split
on null)

表达式错误(如对null值执行
split

If the error mentions
InvalidTemplate
or a function name:
  1. Find the action in the definition
  2. Check what upstream action/expression it reads
  3. Inspect that upstream action's output for null / missing fields
python
undefined
如果错误提及
InvalidTemplate
或函数名称:
  1. 在定义中找到对应的操作
  2. 检查它读取的上游操作/表达式
  3. 检查上游操作的输出是否存在null/缺失字段
python
undefined

Example: action uses split(item()?['Name'], ' ')

示例:操作使用split(item()?['Name'], ' ')

→ null Name in the source data

→ 源数据中Name字段为null

result = mcp("get_live_flow_run_action_outputs", ..., actionName="Compose_Names")
result = mcp("get_live_flow_run_action_outputs", ..., actionName="Compose_Names")

Returns a single-element array; index [0] to get the action object

返回单元素数组;通过索引[0]获取操作对象

if not result: print("No outputs returned for Compose_Names") names = [] else: names = result[0].get("outputs", {}).get("body") or [] nulls = [x for x in names if x.get("Name") is None] print(f"{len(nulls)} records with null Name")
undefined
if not result: print("Compose_Names无输出返回") names = [] else: names = result[0].get("outputs", {}).get("body") or [] nulls = [x for x in names if x.get("Name") is None] print(f"有{len(nulls)}条记录的Name字段为null")
undefined

Wrong Field Path

字段路径错误

Expression
triggerBody()?['fieldName']
returns null →
fieldName
is wrong. Check the trigger output shape with:
python
mcp("get_live_flow_run_action_outputs", ..., actionName="<trigger-action-name>")
表达式
triggerBody()?['fieldName']
返回null →
fieldName
路径错误。 使用以下命令检查触发器输出格式:
python
mcp("get_live_flow_run_action_outputs", ..., actionName="<trigger-action-name>")

Connection / Auth Failures

连接/授权故障

Look for
ConnectionAuthorizationFailed
— the connection owner must match the service account running the flow. Cannot fix via API; fix in PA designer.

如果出现
ConnectionAuthorizationFailed
错误 — 连接所有者必须与运行流的服务账户匹配。无法通过API修复;请在Power Automate设计器中处理。

Step 7 — Apply the Fix

步骤7 — 应用修复

For expression/data issues:
python
defn = mcp("get_live_flow", environmentName=ENV, flowName=FLOW_ID)
acts = defn["properties"]["definition"]["actions"]
针对表达式/数据问题
python
defn = mcp("get_live_flow", environmentName=ENV, flowName=FLOW_ID)
acts = defn["properties"]["definition"]["actions"]

Example: fix split on potentially-null Name

示例:修复对可能为null的Name字段执行split的问题

acts["Compose_Names"]["inputs"] =
"@coalesce(item()?['Name'], 'Unknown')"
conn_refs = defn["properties"]["connectionReferences"] result = mcp("update_live_flow", environmentName=ENV, flowName=FLOW_ID, definition=defn["properties"]["definition"], connectionReferences=conn_refs)
print(result.get("error")) # None = success

> ⚠️ `update_live_flow` always returns an `error` key.
> A value of `null` (Python `None`) means success.

---
acts["Compose_Names"]["inputs"] =
"@coalesce(item()?['Name'], 'Unknown')"
conn_refs = defn["properties"]["connectionReferences"] result = mcp("update_live_flow", environmentName=ENV, flowName=FLOW_ID, definition=defn["properties"]["definition"], connectionReferences=conn_refs)
print(result.get("error")) # None表示成功

> ⚠️ `update_live_flow`接口始终返回`error`键。
> 值为`null`(Python中为`None`)表示操作成功。

---

Step 8 — Verify the Fix

步骤8 — 验证修复效果

python
undefined
python
undefined

Resubmit the failed run

重新提交故障运行实例

resubmit = mcp("resubmit_live_flow_run", environmentName=ENV, flowName=FLOW_ID, runName=RUN_ID) print(resubmit)
resubmit = mcp("resubmit_live_flow_run", environmentName=ENV, flowName=FLOW_ID, runName=RUN_ID) print(resubmit)

Wait ~30 s then check

等待约30秒后检查

import time; time.sleep(30) new_runs = mcp("get_live_flow_runs", environmentName=ENV, flowName=FLOW_ID, top=3) print(new_runs[0]["status"]) # Succeeded = done
undefined
import time; time.sleep(30) new_runs = mcp("get_live_flow_runs", environmentName=ENV, flowName=FLOW_ID, top=3) print(new_runs[0]["status"]) # Succeeded表示修复完成
undefined

Testing HTTP-Triggered Flows

测试HTTP触发的流

For flows with a
Request
(HTTP) trigger, use
trigger_live_flow
instead of
resubmit_live_flow_run
to test with custom payloads:
python
undefined
对于使用
Request
(HTTP)触发器的流,请使用
trigger_live_flow
而非
resubmit_live_flow_run
,以便使用自定义payload进行测试:
python
undefined

First inspect what the trigger expects

首先检查触发器的预期格式

schema = mcp("get_live_flow_http_schema", environmentName=ENV, flowName=FLOW_ID) print("Expected body schema:", schema.get("triggerSchema")) print("Response schemas:", schema.get("responseSchemas"))
schema = mcp("get_live_flow_http_schema", environmentName=ENV, flowName=FLOW_ID) print("预期请求体格式:", schema.get("triggerSchema")) print("响应格式:", schema.get("responseSchemas"))

Trigger with a test payload

使用测试payload触发流

result = mcp("trigger_live_flow", environmentName=ENV, flowName=FLOW_ID, body={"name": "Test User", "value": 42}) print(f"Status: {result['status']}, Body: {result.get('body')}")

> `trigger_live_flow` handles AAD-authenticated triggers automatically.
> Only works for flows with a `Request` (HTTP) trigger type.

---
result = mcp("trigger_live_flow", environmentName=ENV, flowName=FLOW_ID, body={"name": "Test User", "value": 42}) print(f"状态:{result['status']}, 响应体:{result.get('body')}")

> `trigger_live_flow`接口会自动处理AAD认证的触发器。
> 仅适用于使用`Request`(HTTP)触发器类型的流。

---

Quick-Reference Diagnostic Decision Tree

快速参考诊断决策树

SymptomFirst Tool to CallWhat to Look For
Flow shows as Failed
get_live_flow_run_error
failedActions[-1]["actionName"]
= root cause
Expression crash
get_live_flow_run_action_outputs
on prior action
null / wrong-type fields in output body
Flow never starts
get_live_flow
check
properties.state
= "Started"
Action returns wrong data
get_live_flow_run_action_outputs
actual output body vs expected
Fix applied but still fails
get_live_flow_runs
after resubmit
new run
status
field

症状首先调用的工具检查要点
流显示为Failed
get_live_flow_run_error
failedActions[-1]["actionName"]
= 根本原因
表达式崩溃对上游操作调用
get_live_flow_run_action_outputs
输出体中的null/类型错误字段
流从未启动
get_live_flow
检查
properties.state
是否为"Started"
操作返回错误数据
get_live_flow_run_action_outputs
实际输出体与预期的差异
已应用修复但仍故障重新提交后调用
get_live_flow_runs
新运行实例的
status
字段

Reference Files

参考文档

  • common-errors.md — Error codes, likely causes, and fixes
  • debug-workflow.md — Full decision tree for complex failures
  • common-errors.md — 错误码、可能原因及修复方案
  • debug-workflow.md — 复杂故障的完整决策树

Related Skills

相关技能

  • flowstudio-power-automate-mcp
    — Core connection setup and operation reference
  • flowstudio-power-automate-build
    — Build and deploy new flows
  • flowstudio-power-automate-mcp
    — 核心连接设置与操作参考
  • flowstudio-power-automate-build
    — 构建与部署新流