The error “No aggregated item, sequence was empty” comes from Jinja2
You get this error message if you try to use Jinja2’s filters to get the min/max of an empty sequence.
I was debugging a Python app recently, and I saw an error message in my logs that I didn’t recognise:
jinja2.exceptions.UndefinedError: No aggregated item, sequence was empty.
I didn’t recognise this error, and I couldn’t find anything about it in Google either. (The only search result for this error is a forum thread about home automation, which has the same issue which only hints at the issue.)
I did some debugging and I worked out where it came from – here are my notes.
What causes this error?
In my traceback, I could see this was coming from Jinja2’s min()
and max()
filters. If you try to get the min and max of an empty list, that causes the error:
import jinja2
t = jinja2.Template("{{ 1 + (my_list|max) }}")
print(t.render(my_list=[]))
Note that the 1 +
is required to cause the error – you have to interact with the my_list|max
value, otherwise it’s undefined and gets rendered as an empty string.
If I’d enabled StrictUndefined
, the error would be thrown even if I just rendered the value in the template, and didn’t try to modify it. Here’s another example:
import jinja2
t = jinja2.Template("{{ my_list|max }}", undefined=jinja2.StrictUndefined)
print(t.render(my_list=[]))
The fix is to ensure you’re not trying to get the min()
or max()
of an empty list – if you’re not certain the input list will be non-empty, add a check beforehand.
Where does this error come from?
Once I knew this error came from Jinja2, I was able to search the Jinja2 codebase and find the function where this error is being returned:
def _min_or_max(
environment: "Environment",
value: "t.Iterable[V]",
...
) -> "t.Union[V, Undefined]":
it = iter(value)
try:
first = next(it)
except StopIteration:
return environment.undefined("No aggregated item, sequence was empty.")
...
Until I saw this code, I didn’t realise Undefined
was an actual type – I’ve only ever encountered it in the sense of “undefined variable”, which is a fairly common programming error, and not necessarily associated with a type.
Digging into this a little further, I discovered that there’s a class jinja2.Undefined
, which is used in several places beyond “your template tried to use a variable that doesn’t exist”.
The documentation also explains why, when I wasn’t using StrictUndefined
, I had to interact with the variable before I could throw an error (emphasis mine):
class jinja2.Undefined
– The default undefined type. This can be printed, iterated, and treated as a boolean. Any other operation will raise an UndefinedError.
This is an interesting idea that I don’t think I’ve come across before. There are lots of languages that have an empty value like null
or undefined
, but I can’t recall seeing any where you can attach an error message that can be used for debugging. It feels similar to something like an Option
or an Err
type, but a value being undefined isn’t necessarily an error.