12.3 Testing and Troubleshooting Cloud Flows
Key Takeaways
- Cloud flow run history is retained for 28 days and exposes per-action inputs, outputs, and durations for every run.
- Resubmit starts a brand-new run using the original trigger inputs — the supported way to re-test after fixing a downstream bug.
- Static results return canned outcomes for selected actions so you can test branch logic without writing to Dataverse or sending email — and forgetting to disable it silently disables the real writes.
- HTTP 429 on Dataverse actions means service protection throttling; fix it by lowering loop concurrency rather than retrying harder.
- When a flow never fires, run history is empty — use Trigger checks, and first verify the flow is turned on and its connections are healthy.
Building the flow is half the job; AB-410 also expects you to diagnose why a run failed — or why it never started. The testing and troubleshooting toolset lives mostly in make.powerautomate.com.
Run history
Open a flow and select the 28-day run history on its detail page. As the name says, history is retained for 28 days. Each run shows its status (Succeeded, Failed, Running, Cancelled), start time, and duration. Drill into a run and every step expands to show its exact inputs and outputs plus per-step duration — this is where you see the JSON an action actually received, not what you assumed it received. For a failed run, the failing step is flagged in red with the error code and message, and the entry often links to connector-specific documentation.
Trigger checks: why a flow did not fire
When a flow never runs, the run history is empty — there is nothing to drill into. Use Trigger checks from the flow's detail menu to see whether the trigger even evaluated. Polling triggers query the source system on a schedule, so a new item can take several minutes to register; webhook-style triggers fire almost instantly. Common reasons a trigger stays silent:
- The flow is turned off — the single most common cause.
- The connection is broken and needs re-authentication.
- Trigger conditions on the trigger exclude the record.
- For Dataverse triggers, the scope (Organization, Business unit, or User) does not cover the record's owner.
Resubmit and cancel
From any finished run you can Resubmit, which starts a brand-new run instance using the same trigger inputs — ideal after fixing a downstream bug, because you do not have to recreate the original event. A stuck or runaway run can be Cancelled from its detail page, and you can bulk-cancel queued runs. A resubmission creates a separate history entry, so the original failure remains available for audit.
Static results
Static results lets you test flow logic without calling real external systems. Enable it in the flow's Testing settings, then mark individual actions — say Send an email or Add a new row — with a static outcome: Succeeded, Failed, or a defined output payload. During a test run those actions return the canned result instantly: no email is sent and no Dataverse row is written. It is the supported way to unit-test branch logic and failure paths safely.
Exam trap: A flow that mysteriously 'stops writing rows' after a round of testing is the classic symptom of static results left enabled. Remember to turn it off when testing is complete.
Flow checker and Peek code
The Flow checker (top right of the designer) lists errors that block saving or turning on the flow — a missing required field, a broken expression — and warnings for things that work but are risky, such as a loop that could exceed limits. Clear all errors before you test.
Peek code (the ... menu on any trigger or action) reveals the underlying JSON definition, including the raw expression inside every field. When a Filter rows OData filter returns zero rows unexpectedly, Peek code shows whether the designer mangled the filter — for example, a dynamic content token inserted where you meant a literal string, or double quotes where single quotes are required.
Common failures
| Symptom | Root cause | Fix |
|---|---|---|
| HTTP 429 on Dataverse actions | Service protection throttling — too many requests in the sliding window (enforced per user per web server, on the order of 6,000 requests per 300 seconds) | Reduce loop concurrency, add delays, or batch into fewer, larger calls |
| 401 / 403 | Connection token expired, or the connection user lacks table privileges through their security role | Re-authenticate the connection under Connections; grant the correct Dataverse security role |
| Apply to each fails with 'evaluated to null' | The array input was null rather than empty — usually a failed or incorrect upstream output | Guard with a Condition on empty(), or wrap the input in coalesce(..., json('[]')) |
| List rows returns nothing | OData filter mistakes — display names instead of logical names, double quotes, wrong operator | Use lowercase logical names and single quotes; verify the real filter with Peek code |
Analytics and lifecycle
At awareness level: the Analytics pane on a flow's detail page shows run counts, success and failure trends, and per-action usage — enough to spot a flow that suddenly starts failing after an update. The Power Platform admin center adds tenant-level reporting for environments and capacity. Know the lifecycle distinctions too: Turn off stops all future triggers but keeps in-flight runs and the full history; a flow generally must be turned on to test it properly; and flows inside a solution should be edited from the solution in a development environment, where solution-aware debugging keeps related flows, apps, and connection references together. A managed solution in production cannot be edited in place — fix it in dev, export, and redeploy instead.
A scheduled flow shows an empty run history even though new rows were added to the monitored Dataverse table yesterday. What should you check first?
Your team needs to verify a flow's failure-handling branch, but testing against the real ticketing API would create incidents in production. Which feature lets you test the branch safely?