When Liquid transform in Logic Apps doesn’t Behave like Liquid: A subtle string to integer pitfall

When Liquid transform in Logic Apps doesn’t Behave like Liquid: A subtle string to integer pitfall

• •
4 minutes

Introduction

Azure Logic Apps provides support for Liquid templates to perform transformations, such as converting JSON to XML or transforming data between systems. This is a widely used feature in integration scenarios, especially when working with enterprise messaging patterns.

However, there is an important nuance that is often overlooked: Logic Apps does not use the official Liquid implementation. Instead, it relies on DotLiquid, a .NET-based implementation of the Liquid templating engine.

While DotLiquid aims to be compatible, it does not fully match the behavior of the original implementation. And this can lead to subtle inconsistencies, especially around type handling and arithmetic operations.

Challenge

In a recent integration scenario at one of my clients, I needed to generate an XML document from a JSON file, where one of the fields represented a termination date. The requirement was straightforward:

  • If the last working day is present in the message, use this date
  • If last working day is empty, use the contract due date.
  • If both are empty, the value should be 31-12-[current year + 10 years]

Naturally, the starting point in the liquid transform was to retrieve the current year:

{%- assign currentYear = 'Now' | Date: 'yyyy' -%}

At first glance, this looks correct. However, this expression returns a string, not a numeric value.

This becomes problematic when attempting arithmetic operations on the value:

{%- assign terminationYear = currentYear | Plus: 10 -%}

Instead of performing numeric addition, DotLiquid treats the operation as a string manipulation. If the current year is 2026, the result is not 2036, but rather concatenated or malformed values such as:

202610

This behavior stems from the fact that DotLiquid does not implicitly convert strings to integers in a reliable way.

Attempts and observations

Several common approaches to force numeric conversion were tested by me. Normally these tricks would help in casting the value to an integer.

| Plus: 0
| Minus: 0
| Times: 1

//
{%- assign terminationYear = currentYear | Times: 1 | Plus: 10 -%}
// This results in output 2026110

In practise, these approaches either:

  • Continue to behave as string operations, or
  • Result in runtime errors such as:
Liquid error: Specified argument was out of the range of valid values. (Parameter 'count')

An interesting observation was that the following does trigger a conversion, and I remembered that I have been using this in the past to cast a string to a decimal value.

| Times: 1.0

This successfully converts the value into a number, but as a floating-point number, resulting in values like 2026.0.

Solution

The key insight is that DotLiquid handles floating-point numbers more reliably than integers when casting types. Therefore, the solution is to:

  1. Convert the string to a float using Times: 1.0
  2. Convert the float back to an integer using Round
  3. Perform the arithmetic operation

The final working implementation:

{%- assign currentYear = 'Now' | Date: 'yyyy' -%}
{%- assign currentYearInt = currentYear | Times: 1.0 | Round -%}
{%- assign terminationYear = currentYearInt | Plus: 10 -%}
{%- assign dateOfTermination = "31-12-" | Append: terminationYear -%}

This produces the expected output:

31-12-2036

Conclusion

This small post highlights an important consideration when working with Liquid in Logic Apps: behavior that appears straightforward in the official Liquid implementation may not translate directly to DotLiquid, causing frustrations and quite some time to resolve the issue (since liquid is particularly hard to debug in the context of Logic Apps.

Key takeaways:

  • If the value comes from the source message (e.g. JSON) and already is a number type, such issues do not occur
  • Date filters return strings, not numbers
  • Arithmetic operations on strings can lead to unexpected concatenation
  • Type conversion in DotLiquid is limited and inconsistent
  • A reliable workaround is to explicitly convert via the given examples

For developers and integration specialists, understanding these small nuances can save significant time. When working with Liquid in Logic Apps, it is often necessary to think not just in terms of syntax, but also in terms of how the underlying engine interprets data types.

If you have encountered similar challenges or alternative approaches, it would be valuable to share experiences.

What’s next?

The frustrating part is that you only find out after a deployment, because Liquid is so hard to debug in Logic Apps. That is why I built la-liquid, an open-source tool that validates and runs your Liquid maps locally with the same engine as Logic Apps, and warns you about pitfalls like this one up front. I’ll introduce it in my next article on November 24.


Leave a Reply

Your email address will not be published. Required fields are marked *