Stop Guessing: Power Automate Trigger Conditions That Actually Work
Stop debugging blind. Test Power Automate trigger conditions in a Compose action first, then ship four no-code recipes that fire only when they should.
In this article · 6 sections
The pattern is common enough to be a cliché. Someone fixes a typo in a SharePoint item and your flow treats it like breaking news, firing off approval emails nobody asked for. Or the opposite: you add a filter, hit save, and the flow goes completely silent, and you have no idea why.
Here is the reframe that fixes this. Power Automate trigger conditions are filters that run before a run is ever created. A trigger is the event that starts a flow, like “a SharePoint item was modified.” An action is what the flow does in response, like “send an approval email.” A trigger condition sits between the two and decides whether the event even counts.
Think of it like an email rule that deletes junk before it reaches your inbox. That “before a run exists” timing is exactly why these conditions feel impossible to debug. There are two distinct failure modes, and it helps to keep them separate. A condition that is written correctly but evaluates to false produces silence: no run, no history, nothing to inspect. A condition that is malformed throws a red error when you try to save it. The red error at least tells you something is wrong. The silence tells you nothing at all.
So the problem is not your syntax. The problem is that you are writing blind. Your manager cares about this too: every filtered-out run is one less junk notification, and every run you do allow counts toward the request limits Microsoft publishes for your license on its limits and configuration page. Trigger conditions are how you spend those runs on work that matters.
The takeaway: stop debugging the trigger. Move the logic somewhere you can see it.
The Build-It-Outside-First Method (About 15 Minutes)
Never write a trigger condition directly into the trigger. Build and test the expression inside a Compose action first, where every run shows you the output, then promote it. This is the right way, and it is the step the Microsoft Learn page on trigger conditions skips. The docs show you where the setting lives and what the syntax looks like. They do not tell you to validate outside first. In my own builds, this habit surfaces “power automate expression evaluation failed” errors while you can still see the data that caused them, instead of after the flow goes silent in production.
Here is the method:
- Fire the trigger with the real event. Edit the actual SharePoint list item. Do not rely on the Test button’s manual run. A manually tested run and a production-fired run do not always produce the same output shape, so an expression that passes a manual test can still fail on the real event.
- Open the run and inspect the trigger’s raw outputs. This is your source of truth for field names. SharePoint stores a permanent internal name set when a column was created. A column later renamed to “Approval Status” often still lives as
StatusorStatus0internally, and your expression must use the internal name. Never hand-type a field path. Copy the keys straight from the raw JSON output. - Add a Compose action and enter your expression. Click into the Compose input, open the expression editor, and type the bare function:
equals(triggerOutputs()?['body']?['Status']?['Value'], 'Approved'). After you insert it, the Compose field itself displays it wrapped as@{...}. That wrapper is just how expressions appear inside action fields; the logic is the bare function you typed. - Fire the real event again and check the Compose output. You want a clean
trueorfalse. Anything else means your path or comparison is wrong, and now you can see exactly why, because the same run shows you the raw payload right next to your result. - Promote the tested expression. Open the trigger’s settings (the three dots on the trigger, then Settings, then Trigger Conditions) and paste in the bare expression with a single
@in front:@equals(triggerOutputs()?['body']?['Status']?['Value'], 'Approved'). That is the one conversion to remember:@{...}is the action costume,@is the trigger costume. Same logic, different jacket. - Delete the Compose action once the condition is live and verified.
You test the logic where you can actually see the output, then you move it. If expressions themselves feel new, our primer on Power Automate expressions basics covers the building blocks before you tackle conditions.
The Three Syntax Rules That Break Everyone
Power Automate shares its expression language with Azure Logic Apps, which means the Workflow Definition Language functions reference is your dictionary for equals, empty, or, and friends. Three rules cover most of the red errors.
| Rule | Wrong | Right |
|---|---|---|
1. Bare @ prefix in triggers, not @{...} | @{equals(triggerOutputs()?['body']?['Status']?['Value'], 'Approved')} | @equals(triggerOutputs()?['body']?['Status']?['Value'], 'Approved') |
| 2. Start with the comparison function, never a bare field | @triggerOutputs()?['body']?['Status'] = 'Approved' | @equals(triggerOutputs()?['body']?['Status']?['Value'], 'Approved') |
| 3. Use the internal name and the full tested path | @equals(triggerBody()?['Approval Status'], 'Approved') | @equals(triggerOutputs()?['body']?['Status']?['Value'], 'Approved') |
In plain language: triggerBody() returns the item’s data. triggerOutputs() returns the whole trigger result, including that data under body. Either works when the path matches what you saw in the raw output, and the nested ?['body']?['Status'] form lets you copy each key straight out of the raw JSON, level by level. The ? is a safety net that returns nothing instead of crashing when a field is missing. Strings take single quotes, and comparisons are case sensitive, so 'approved' does not equal 'Approved'.
Three fixes, and most red-error trigger conditions disappear.
Four Power Automate Trigger Conditions That Hold Up
These are the power automate trigger conditions examples worth stealing. The expressions follow the shapes the SharePoint connector returns, but field shapes and internal names vary by list and by connector version, so run each one through the Compose method against your own raw output before promoting it. That is the whole point of the method.
Recipe 1: Only when Status equals Approved. This is the workhorse of power automate trigger conditions sharepoint makers reach for first, because it stops an approval flow from firing on drafts. It pairs perfectly with the flow you get when you build your first approval flow.
@equals(triggerOutputs()?['body']?['Status']?['Value'], 'Approved')
Gotcha: in the SharePoint payload, a choice column comes back as an object, not plain text, which is why the ?['Value'] sits on the end. Confirm that shape in your own raw output, and remember the internal name rule: the display name “Approval Status” is not what the payload calls the column.
Recipe 2: Only on creation, not on every edit. The right answer is the dedicated “When an item is created” trigger from the SharePoint connector, with no condition at all. When you are stuck on “When an item is created or modified” because one flow handles both cases, the timestamp fallback works:
@equals(triggerOutputs()?['body']?['Created'], triggerOutputs()?['body']?['Modified'])
Gotcha: on a genuine creation, both stamps come from the same save and match in the payload. But anything that touches the item before your trigger fires breaks the equality, including another flow, a list rule, or a fast-fingered colleague. Create a fresh test item and compare the two values in your raw output before trusting this. Prefer the dedicated trigger whenever you can.
Recipe 3: Ignore my own edits. The second essential power automate trigger conditions sharepoint pattern, because a flow that updates the item it watches will retrigger itself.
Infinite-loop warning. A flow that edits its own watched item retriggers itself, burning through your run allowance and flooding inboxes until someone turns it off. Do not count on the platform to rescue you. Design the guard yourself with a condition that excludes the flow’s own writes.
@not(equals(triggerOutputs()?['body']?['Editor']?['Email'], 'flow-connection@yourcompany.com'))
Gotcha: do not guess that email address. The edits come from whatever account owns the flow’s SharePoint connection, so let the flow update an item once, open that run’s raw output, and copy the editor email exactly as the payload shows it. Person columns arrive as nested objects in the SharePoint payload, so verify the full path while you are in there.
Recipe 4: Skip blanks. The power automate trigger conditions null guard that stops your flow from emailing about items missing a due date:
@not(empty(triggerOutputs()?['body']?['DueDate']))
Gotcha: null means the field was never set, blank means it holds an empty value. empty() treats both as empty, which is exactly what you want here.
The honest limit: trigger conditions cannot see the past. A trigger condition sees only the item’s current state, never its previous version, so it cannot detect “only when this field changed to a new value” on its own. The right pattern: use the condition to cut the obvious noise, then use the SharePoint action “Get changes for an item or a file (properties only)” inside the flow to detect the actual change. This is a limit of the platform, not a failure of your build.
Four conditions you can adapt today, plus the one thing they cannot do.
Multiple Power Automate Trigger Conditions: The AND vs OR Trap
The trigger settings pane lets you add several condition boxes, and here is the trap with multiple Power Automate trigger conditions: every box must be true, which narrows your trigger far more than most makers expect. Microsoft’s docs do not spell this out, but you can verify it in two minutes: add two conditions that cannot both be true and watch the flow go silent.
That silence is the tell. When someone says “my flow stopped triggering at all,” it is usually not broken. It is over-filtered, because they stacked boxes when they meant OR. To get OR logic, write one expression:
@or(equals(triggerOutputs()?['body']?['Status']?['Value'], 'Approved'), equals(triggerOutputs()?['body']?['Status']?['Value'], 'Rejected'))
When any one of your conditions should let the flow run, put them all inside a single or() expression. Reserve separate boxes for logic where everything genuinely must be true at once.
Verify Before You Ship
You might be thinking: what if I break something? Trigger conditions are among the safest things you can change in a flow, because the worst outcomes are a flow that runs too often or not at all, and this checklist catches both. It takes five minutes.
- Force a true case with the real event. Edit the actual list item so the condition should pass, and confirm a run appears.
- Force a false case. Edit the item so the condition should fail, and confirm the flow stays silent. Silence on purpose is the win here.
- Check for phantom runs. Look at run history over the next day and confirm nothing fired that should not have.
- Document the condition in plain English in the flow’s description: “Only runs when Status is Approved and the editor is not the flow’s connection account.” Future-you will not remember, and teammates should not have to decode expressions.
You just made a flow that fires only when it should, with a paper trail. No code required.
What to Ask Your IT Department
You need three confirmations, and trigger conditions make this an easy yes because they cut run volume, which IT likes. To find your environment name (an environment is a workspace for your apps and flows), look at the environment picker in the top-right corner of make.powerautomate.com. Then send this:
Subject: Quick check before I build a Power Automate flow Hi [IT contact], I am building a flow that starts when a SharePoint item changes, filtered with trigger conditions so it only runs when it should. Before I build it, can you confirm three things? 1) I have maker access in the [environment name] environment. 2) Our DLP policy allows the SharePoint connector in that environment. 3) My current license covers roughly [X] runs per month. I am adding trigger conditions specifically to keep run volume low. Happy to walk you through the flow design if useful. Thanks!
A DLP policy is IT’s rulebook for which connectors (pre-built bridges to apps like SharePoint or Outlook) can talk to each other. Do not work around it. Send the email before you build, and the flow you tested with the Compose method ships without a governance surprise waiting at the end.
Stay in the loop
Get new posts delivered to your inbox. No spam, unsubscribe anytime.
Related articles
Stop Guessing: Power Automate formatDateTime and the Timezone Trap Nobody Warns You About
Fix wrong dates in your flows for good: Power Automate formatDateTime traps, the convert-first timezone pattern, and a copy-paste reference table.
SharePoint Alerts Are Weak: Replace SharePoint Alerts With Power Automate
Classic SharePoint alerts fire on everything and get ignored. Here is how to replace SharePoint alerts with Power Automate and send notifications people actually read. No code.