Skip to content

[power-automate][Bug] #314 not fixed in 2.3.1 — solution-flow clientdata path is gated on the get_flow_context false-negative dismissed in #318 #342

Description

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 reproducedMay 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:

  1. 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.
  2. 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.
  3. 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

  1. 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.
  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.
  3. 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

  1. Create an unmanaged solution containing a connection reference (<prefix>_SharePoint → SharePoint connector).
  2. 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).
  3. Call get_flow_context(flow=<ppapiFlowId>) → returns inSolution: false with warning: "workflow-not-found" (see Logs).
  4. Attempt a surgical edit:
edit_flow(flow=<ppapiFlowId>, operations=[
  {"op":"merge","path":"actions/<Action>/metadata","value":{"probe":"1"}}])

WorkflowRunActionInputsMissingProperty: … Property 'host.connectionReferenceName' is missing.

  1. 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.

  1. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions