Checking if something is empty can save a lot of actions and potentially breaking flows. That's why we have the "empty" function that will check if a collection is empty or not. It's one of those Power Automate functions you end up using in almost every flow, usually right before you try to read something that may not be there.
One important distinction is that empty is not the same thing as "Null". I see a lot of people making this confusion. Think of it like this. If you have an empty pack of cookies, the pack still exists, although empty. But if your hands are empty, that's where "Null" comes into play. You can't compare something if it doesn't exist; hence the flow breaks when something is "Null". The good news is that the "empty" function itself copes with both. It returns true for an empty collection and for "Null", which is why it's such a handy guard before you use a value.
So let's check how the "empty" function works.
Usage
It follows a simple pattern.
- String with a collection or,
- Collection
It will always return a true/false result.
empty('<collection>')
empty([<collection>])
| Parameter | Required | Type | Description |
|---|---|---|---|
| collection | Yes | String, Array, or Object | The collection to check |
Let's start with a simple example:
empty(variables('ARRAY_VARIABLE'))
will return
true
The variable was initialized without any value, so the "empty" function returns that it is indeed true.
Now, how about instead we provide:
empty('[]')
will return
false
Why? Notice that we're not providing an array. Instead, we're providing a string that has content. Since a string with content can be considered a collection, the result is false.
Let's now check how it works with the "createArray" function, by creating an array with one element.
empty(createArray(1))
will return
false
Makes sense. The "createArray" function creates an array with one element, so it's not empty.
Finally, let's provide an empty string from a variable:
empty(variables('EMPTY_STRING'))
will return
true
The "empty" function checks if an object is empty (remember the pack of cookies from before). It can check because we define the type, so the "empty" function knows how to check if it's empty or not.
Real-world examples
Here are two spots where the "empty" function does most of the heavy lifting in my flows.
Checking a list before grabbing the first item
We query a SharePoint list, and sometimes it comes back with nothing at all. The "first" function won't complain about that, it quietly returns null, and then the next action breaks. So let's check before we reach in.
if(empty(body('Get_items')?['value']), null, first(body('Get_items')?['value']))
Now we get a predictable null instead of a surprise further down the flow.
Giving a blank field a default value
A form field is optional, so people leave it blank. Instead of building a whole Condition around it, we can handle it in one expression with the "if" function.
if(empty(triggerOutputs()?['body/Department']), 'Unassigned', triggerOutputs()?['body/Department'])
If the department is missing, we get "Unassigned". If someone typed something, we get exactly what they typed.
Non-intuitive behaviors
"Null" comes back as true
Given the distinction we drew at the top, you would be forgiven for expecting "empty" to fall over when it meets a "Null". It doesn't. Microsoft's expression cookbook is explicit that "empty(null)" returns true, exactly like "empty('')" does. That's the whole reason we reach for it as a guard. One call covers both the field that came back blank and the field that wasn't there at all, so we don't need to test for them separately.
Whitespace is not empty
A field that looks blank on screen may still hold a space or two, and "empty" counts those as content, so it returns false. This one catches people out on optional text fields where someone tapped the space bar. If we want a stray space to count as blank, we can wrap the value in the "trim" function first.
empty(trim(triggerOutputs()?['body/Comments']))
Now a value of " " gives us true, which is usually what we meant in the first place.
Numbers are not collections
The function only accepts a string, an array, or an object. Microsoft's reference is explicit about that, and the expression cookbook adds that "empty(0)" throws an error instead of returning true or false. Booleans behave the same way, which is why nesting two "empty" calls fails (more on that in the recommendations below). If you need to know whether a number is missing, compare it directly rather than reaching for "empty". The cookbook points at "equals" for that, along the lines of "equals(variables('NUMBER_VARIABLE'), null)".
"coalesce" answers a different question
It's tempting to swap in the "coalesce" function whenever a value might be missing, but the two look at different things. "coalesce" walks its parameters and hands back the first one that isn't null, and Microsoft is clear that empty strings, empty arrays, and empty objects aren't null. So "coalesce('', 'fallback')" gives us the empty string, not the fallback. When blank matters just as much as missing, "empty" is the one we want.
Some type errors only show up when the flow runs
When we hand "empty" a constant it can't work with, the designer catches it while we're saving and shows an InvalidTemplate error. When that same unusable value arrives through a variable or an action output, nothing complains at save time and the flow fails mid-run instead. It's worth keeping in mind when a flow that saved perfectly still falls over on the first real record.
Limitations
Depending on the size of your string, your expression may return an error, even if it's correct. Please note that the expressions have a max size of 8,192 characters. If you have an expression bigger than 1,000 characters, I would strongly advise breaking it into smaller, manageable formulas.
That number is still the documented cap. Microsoft lists it as "Characters per expression" in the flow limits documentation.
Recommendations
Here are some things to keep in mind.
Use "debug" Compose actions
Since the comparison will return true or false, sometimes it's tricky to understand how the calculation is done, depending on how complex the expression is. So I recommend using "Compose" actions to have the values that go "in" the function. This way, if the value doesn't make sense, you can understand, based on the parameters, why it was calculated that way.
Don't nest
There's no real reason to do it. The flow will allow you to nest "empty" functions in a formula, but then it will return the following error when it runs.
Unable to process template language expressions in action 'Compose' inputs at line '1' and column '4718': 'The template language function 'empty' expects its parameter to be an object, an array or a string. The provided value is of type 'Boolean'. Please see https://aka.ms/logicexpressions#empty for usage details.'.
The "empty" function cannot have a boolean as a parameter, as explained by the exception.
Make "coalesce" skip blanks too
We saw earlier that the "coalesce" function walks past "Null" but happily hands back an empty string. If we want it to skip blanks as well, we can wrap each candidate in an "empty" check that turns a blank into a "Null" first.
coalesce(if(empty(variables('NICKNAME')), null, variables('NICKNAME')), if(empty(variables('FIRST_NAME')), null, variables('FIRST_NAME')), 'Unknown')
It's a little long-winded, but it's the pattern Microsoft documents, and it saves building a chain of Conditions.
Final Thoughts
The "empty" function is a small one, but it saves us from a lot of broken runs. Check the collection before you use it, keep the expression short enough to read, and remember it only wants a string, an array, or an object. Do that, and it will quietly do its job in the background of every flow you build.
Sources
- empty function, workflow expression functions reference
- Expression cookbook for cloud flows
- Limits of automated, scheduled, and instant flows
- Cloud flow error code reference
Back to the Power Automate Function Reference
Photo by Tijs van Leur on Unsplash
What's the best approach for properties that are expecting an integer where the value is null/empty? I know you can convert the integer to a string, so 'if empty' can then be used. For context, a successful error (200) won't return 'status' only 'statusCode' (which is an integer). In a Compose step, if I use: if(empty(body('Parse_JSON_|_get_error_details')?['body']?['status']), '200', body('Parse_JSON_|_get_error_details')?['body']?['status']) ..for successful (statusCode 200) runs, it complains that empty can't be used as it's an integer value - with the error: InvalidTemplate. Unable to process template language expressions in action 'Compose_|_Error_message' inputs at line '0' and column '0': 'The template language function 'empty' expects its parameter to be an object, an array or a string. The provided value is of type 'Integer' If there's a neater expression to handle integers where Null values are returned, that'd be great. Possibly another way is to allow the Parse JSON schema to accept null values, eg: "type": ["integer", "null"] Thanks!