Plugin
power-automate
Plugin Version
2.3.1 (the release that closed #314 via #318)
Skill / Command
N/A — FlowAgent MCP tools: update_flow, edit_flow, get_flow_context, copy_flow, run_flow
Bug Description
Follow-up to #314, closed as completed by #318. Findings 1–3 still reproduce on 2.3.1, on a different tenant and a brand-new unmanaged solution. Filing a new issue because we don't have permission to reopen #314.
We believe this is a single interaction between two of the original findings rather than three separate regressions — and that the fix in #318 is correct but unreachable.
From #318:
Fix: updateFlow detects solution flows via get_flow_context and uses Dataverse clientdata PATCH instead of PPAPI. Falls back to PPAPI for non-solution flows.
and:
Finding 3: get_flow_context false-negative — Not reproduced … May be env-specific.
Finding 3 is the gate on the finding-2 fix. If get_flow_context reports inSolution: false, updateFlow takes the PPAPI fallback — which is the 2.1.0 behaviour. So on any environment where finding 3 occurs, the finding-2 fix never executes. Ours is such an environment.
Root cause of the finding-3 false-negative: getFlowContext resolves the flow in Dataverse by the PPAPI flow id, but those are different values. Our flow has three distinct ids:
|
value (redacted) |
PPAPI name |
f959… |
properties.workflowEntityId (= Dataverse workflowid) |
c12e… |
properties.workflowUniqueId |
847c… |
workflows(<ppapiFlowId>) → 404; workflows(<workflowEntityId>) → 200. workflowEntityId is already present in the same PPAPI response getFlowContext itself fetches, but is not used.
That is very likely the whole of "may be env-specific": on environments where the PPAPI id happens to equal the workflowid, the lookup succeeds by coincidence and both finding 3 and this gating problem become invisible.
(For the record: the Dataverse workflowid exists from creation — we read it while the flow was outside any solution — so this is not about acquiring an id on entering a solution.)
The #318 approach is correct — we verified it by hand. Doing manually what #318 says updateFlow should do works:
GET {org}/api/data/v9.2/workflows({workflowid})?$select=clientdata
→ edit properties.definition.* in the parsed JSON string
PATCH {org}/api/data/v9.2/workflows({workflowid}) { "clientdata": "<modified>" }
The change persisted, propagated to the PPAPI surface (get_flow returned the injected key), the connection reference stayed intact, the flow stayed activated (statecode 1, no deactivate/reactivate needed), and PATCHing the original back restored it byte-identically. So this is not a disagreement about the remedy — the remedy is right and simply never runs.
Questions about the verification. #318 reports "Verified on test tenant: flow with shared_approvals + shared_office365 + shared_teams in unmanaged solution round-trips successfully." Given the above:
- For that flow, did
properties.workflowEntityId equal the PPAPI flow id? If it did, the clientdata path was reached only because the Dataverse lookup coincidentally succeeded.
- Was
get_flow_context asserted to return inSolution: true in that same test? If finding 3 was "not reproduced" on the test tenant, then the finding-2 fix and the finding-3 bug were never exercised together — so their interaction would go untested by construction.
- Is there a regression test that forces
inSolution: false and asserts the clientdata path is still chosen (or that the failure surfaces rather than silently falling back to PPAPI)?
Suggested fix
- Resolve the workflow via
properties.workflowEntityId (already fetched), falling back to workflowUniqueId, before concluding workflow-not-found. This fixes finding 3 and thereby ungates finding 2.
- Don't silently fall back to PPAPI when the Dataverse lookup fails and the flow has
connectionReferenceLogicalNames — that combination means the PPAPI path is guaranteed to fail, so a clear error beats a confusing host.connectionReferenceName message.
- Related: the guard is documented fail-open, so on affected environments the managed-solution write protection is silently inactive as well.
Two further defects found on 2.3.1
Steps to Reproduce
- Create an unmanaged solution containing a connection reference (
<prefix>_SharePoint → SharePoint connector).
- In the maker portal, create a cloud flow inside that solution: manual trigger + one SharePoint action (we used
ListFolder). Its stored definition is therefore whatever the product itself writes. Confirm the flow is a solution component via Dataverse solutioncomponents (componenttype 29).
- Call
get_flow_context(flow=<ppapiFlowId>) → returns inSolution: false with warning: "workflow-not-found" (see Logs).
- Attempt a surgical edit:
edit_flow(flow=<ppapiFlowId>, operations=[
{"op":"merge","path":"actions/<Action>/metadata","value":{"probe":"1"}}])
→ WorkflowRunActionInputsMissingProperty: … Property 'host.connectionReferenceName' is missing.
- Attempt
update_flow with the full definition, in every host/map combination we could construct:
host.connectionReferenceName |
connectionReferences keyed by |
Result |
omitted (connectionName instead) |
connector name |
host.connectionReferenceName is missing |
<prefix>_SharePoint (logical name) |
connector name |
The API connection reference '<prefix>_SharePoint' could not be found |
shared_sharepointonline (connector name) |
connector name |
The API connection reference 'shared_sharepointonline' could not be found |
<prefix>_SharePoint |
logical name |
The 'host.connectionReferenceName' property value is of type 'Null'. The value must be a literal string. |
The last row is worth attention: the property was sent as a literal string. With a non-connector map key it arrives null, which suggests host is rebuilt from the refs map.
copy_flow(flow=<ppapiFlowId>) → TypeError: ctx.getClient(...).copyFlow is not a function.
Expected Behavior
edit_flow / update_flow succeed on connection-reference flows in unmanaged solutions on any environment — not only where the PPAPI flow id happens to coincide with the Dataverse workflowid.
get_flow_context correctly resolves unmanaged-solution membership, so the clientdata write path added in #318 is actually reached.
Actual Behavior
get_flow_context reports inSolution: false / warning: "workflow-not-found" for a flow that verifiably is a solution component, so updateFlow falls back to PPAPI and every edit fails with host.connectionReferenceName errors — identical to 2.1.0 behaviour. copy_flow throws a TypeError. run_flow cannot trigger invoker-source flows.
Relevant Logs / Screenshots
get_flow_context on a flow that is a component of an unmanaged solution:
{
"workflowId": null,
"workflowIdUnique": null,
"inSolution": false,
"solutionUniqueName": null,
"connectionReferenceLogicalNames": ["<prefix>_SharePoint"],
"warning": "workflow-not-found"
}
Note it resolves the connection-reference logical names from PPAPI while failing the Dataverse lookup.
The stored Dataverse clientdata for the same designer-created solution flow — i.e. the shape the product itself persists:
{ "properties": {
"connectionReferences": {
"shared_sharepointonline": {
"runtimeSource": "invoker",
"connection": { "connectionReferenceLogicalName": "<prefix>_SharePoint" },
"api": { "name": "shared_sharepointonline" } } },
"definition": { "actions": { "<Action>": { "inputs": {
"host": { "connectionName": "shared_sharepointonline",
"operationId": "ListFolder",
"apiId": "/providers/Microsoft.PowerApps/apis/shared_sharepointonline" },
"authentication": { "type": "Raw",
"value": "@json(decodeBase64(triggerOutputs().headers['X-MS-APIM-Tokens']))['$ConnectionKey']" }
} } } } },
"schemaVersion": "1.0.0.0" }
host.connectionName = the connector name, inline authentication present, and the reference nested under connection.connectionReferenceLogicalName. That is a different schema from what the PPAPI write path validates against, which is the underlying reason no PPAPI round-trip can succeed.
Full error from edit_flow (German locale on the service side):
Flow API 400 Bad Request: XrmApiRequestFailed → InvalidOpenApiFlow:
"Fehler beim Speichern des Flows. Code: WorkflowRunActionInputsMissingProperty,
Meldung: The 'inputs' of workflow run action '<Action>' of type 'OpenApiConnection'
is not valid. Property 'host.connectionReferenceName' is missing."
Code: 0x80060467
run_flow against the same flow:
AzureResourceManagerRequestFailed → InvokerConnectionOverrideFailed:
"Failed to parse invoker connections from trigger 'manual' outputs. Exception:
Could not find property 'headers.X-MS-APIM-Tokens' in the trigger outputs.
Workflow has connection references '[\"shared_sharepointonline\"]' with invoker runtime source."
All tenant, environment, site, connection and workflow identifiers have been replaced with placeholders.
Environment
- OS: Windows 11 Enterprise (10.0.26200)
- PAC CLI: 2.10.1 (running under WSL Ubuntu-24.04, .NET 10)
- Plugin: power-automate 2.3.1
- Auth:
az login (delegated user), Dataverse Web API v9.2 reachable and verified via WhoAmI
- Dataverse environment type: Sandbox, region Europe
🤖 This issue was created using the /report-issue skill.
Plugin
power-automate
Plugin Version
2.3.1 (the release that closed #314 via #318)
Skill / Command
N/A — FlowAgent MCP tools:
update_flow,edit_flow,get_flow_context,copy_flow,run_flowBug Description
Follow-up to #314, closed as completed by #318. Findings 1–3 still reproduce on 2.3.1, on a different tenant and a brand-new unmanaged solution. Filing a new issue because we don't have permission to reopen #314.
We believe this is a single interaction between two of the original findings rather than three separate regressions — and that the fix in #318 is correct but unreachable.
From #318:
and:
Finding 3 is the gate on the finding-2 fix. If
get_flow_contextreportsinSolution: false,updateFlowtakes the PPAPI fallback — which is the 2.1.0 behaviour. So on any environment where finding 3 occurs, the finding-2 fix never executes. Ours is such an environment.Root cause of the finding-3 false-negative:
getFlowContextresolves the flow in Dataverse by the PPAPI flow id, but those are different values. Our flow has three distinct ids:namef959…properties.workflowEntityId(= Dataverseworkflowid)c12e…properties.workflowUniqueId847c…workflows(<ppapiFlowId>)→ 404;workflows(<workflowEntityId>)→ 200.workflowEntityIdis already present in the same PPAPI responsegetFlowContextitself fetches, but is not used.That is very likely the whole of "may be env-specific": on environments where the PPAPI id happens to equal the
workflowid, the lookup succeeds by coincidence and both finding 3 and this gating problem become invisible.(For the record: the Dataverse
workflowidexists from creation — we read it while the flow was outside any solution — so this is not about acquiring an id on entering a solution.)The #318 approach is correct — we verified it by hand. Doing manually what #318 says
updateFlowshould do works:The change persisted, propagated to the PPAPI surface (
get_flowreturned the injected key), the connection reference stayed intact, the flow stayed activated (statecode 1, no deactivate/reactivate needed), and PATCHing the original back restored it byte-identically. So this is not a disagreement about the remedy — the remedy is right and simply never runs.Questions about the verification. #318 reports "Verified on test tenant: flow with shared_approvals + shared_office365 + shared_teams in unmanaged solution round-trips successfully." Given the above:
properties.workflowEntityIdequal the PPAPI flow id? If it did, the clientdata path was reached only because the Dataverse lookup coincidentally succeeded.get_flow_contextasserted to returninSolution: truein that same test? If finding 3 was "not reproduced" on the test tenant, then the finding-2 fix and the finding-3 bug were never exercised together — so their interaction would go untested by construction.inSolution: falseand asserts the clientdata path is still chosen (or that the failure surfaces rather than silently falling back to PPAPI)?Suggested fix
properties.workflowEntityId(already fetched), falling back toworkflowUniqueId, before concludingworkflow-not-found. This fixes finding 3 and thereby ungates finding 2.connectionReferenceLogicalNames— that combination means the PPAPI path is guaranteed to fail, so a clear error beats a confusinghost.connectionReferenceNamemessage.Two further defects found on 2.3.1
copy_flowis unwired —TypeError: ctx.getClient(...).copyFlow is not a function. Same class as the originaleditFlowdefect (cf. [power-automate][Bug] copy_flow fails with "ctx.getClient(...).copyFlow is not a function #289/[power-automate][Bug] copy_flow and edit_flow crash with TypeError: ctx.getClient(...).copyFlow/editFlow is not a function #294).run_flowcannot triggerruntimeSource: "invoker"flows —InvokerConnectionOverrideFailed: Could not find property 'headers.X-MS-APIM-Tokens' in the trigger outputs. Designer-created connection-reference flows are invoker-source, so manual test runs must be started from the portal. Reproduced identically before and after an unrelated clientdata edit, so it is inherent, not edit-induced; agent-created flows withsource: "Embedded"run fine. Ideallyrun_floweither supplies the header or fails with an explanatory message.Steps to Reproduce
<prefix>_SharePoint→ SharePoint connector).ListFolder). Its stored definition is therefore whatever the product itself writes. Confirm the flow is a solution component via Dataversesolutioncomponents(componenttype 29).get_flow_context(flow=<ppapiFlowId>)→ returnsinSolution: falsewithwarning: "workflow-not-found"(see Logs).→
WorkflowRunActionInputsMissingProperty: … Property 'host.connectionReferenceName' is missing.update_flowwith the full definition, in every host/map combination we could construct:host.connectionReferenceNameconnectionReferenceskeyed byconnectionNameinstead)host.connectionReferenceName is missing<prefix>_SharePoint(logical name)The API connection reference '<prefix>_SharePoint' could not be foundshared_sharepointonline(connector name)The API connection reference 'shared_sharepointonline' could not be found<prefix>_SharePointThe 'host.connectionReferenceName' property value is of type 'Null'. The value must be a literal string.The last row is worth attention: the property was sent as a literal string. With a non-connector map key it arrives null, which suggests
hostis rebuilt from the refs map.copy_flow(flow=<ppapiFlowId>)→TypeError: ctx.getClient(...).copyFlow is not a function.Expected Behavior
edit_flow/update_flowsucceed on connection-reference flows in unmanaged solutions on any environment — not only where the PPAPI flow id happens to coincide with the Dataverseworkflowid.get_flow_contextcorrectly resolves unmanaged-solution membership, so the clientdata write path added in #318 is actually reached.Actual Behavior
get_flow_contextreportsinSolution: false/warning: "workflow-not-found"for a flow that verifiably is a solution component, soupdateFlowfalls back to PPAPI and every edit fails withhost.connectionReferenceNameerrors — identical to 2.1.0 behaviour.copy_flowthrows aTypeError.run_flowcannot trigger invoker-source flows.Relevant Logs / Screenshots
get_flow_contexton a flow that is a component of an unmanaged solution:{ "workflowId": null, "workflowIdUnique": null, "inSolution": false, "solutionUniqueName": null, "connectionReferenceLogicalNames": ["<prefix>_SharePoint"], "warning": "workflow-not-found" }Note it resolves the connection-reference logical names from PPAPI while failing the Dataverse lookup.
The stored Dataverse
clientdatafor the same designer-created solution flow — i.e. the shape the product itself persists:{ "properties": { "connectionReferences": { "shared_sharepointonline": { "runtimeSource": "invoker", "connection": { "connectionReferenceLogicalName": "<prefix>_SharePoint" }, "api": { "name": "shared_sharepointonline" } } }, "definition": { "actions": { "<Action>": { "inputs": { "host": { "connectionName": "shared_sharepointonline", "operationId": "ListFolder", "apiId": "/providers/Microsoft.PowerApps/apis/shared_sharepointonline" }, "authentication": { "type": "Raw", "value": "@json(decodeBase64(triggerOutputs().headers['X-MS-APIM-Tokens']))['$ConnectionKey']" } } } } } }, "schemaVersion": "1.0.0.0" }host.connectionName= the connector name, inlineauthenticationpresent, and the reference nested underconnection.connectionReferenceLogicalName. That is a different schema from what the PPAPI write path validates against, which is the underlying reason no PPAPI round-trip can succeed.Full error from
edit_flow(German locale on the service side):run_flowagainst the same flow:All tenant, environment, site, connection and workflow identifiers have been replaced with placeholders.
Environment
az login(delegated user), Dataverse Web API v9.2 reachable and verified viaWhoAmI🤖 This issue was created using the
/report-issueskill.