"Matches regex" evaluation: which regex format?

Describe the problem/error/question

My IF nodes containing a “matches regex” operator doesn’t behave as it used to.

I have a IF node comparing strings.
The left-hand operator is {{ $json.value1 }} and the right hand is abc|def
This used to be a match in previous n8n versions when $json.value1 is, for example, abc123.
It no longer matches.

What is the error message (if any)?

My regex are validated with regex101 Flavor python.
I tried other formats, but they all fail.
The n8n docs and chatbot cannot confirm what exact regex format is expect by n8n for the “matches regex” operator.

I can’t figure out how to proceed, can someone please give me pointers?
Thanks!

Please share your workflow

Information on your n8n setup

  • n8n version: 2.9.2 and 2.13.2
  • **Database (default: SQLite): sqlite
  • Running n8n via (Docker, npm, n8n cloud, desktop app): Docker
  • Operating system: Ubuntu

Hi @jb8n
I’d say n8n is expecting JavaScript-style regex here, not Python regex, so if I wanted abc123 to match, I’d try ^(abc|def) instead of just abc|def. If I wanted it to match anywhere in the string, I’d use .(abc|def). instead. Since there have also been recent reports about | behaving oddly in matches regex, I wouldn’t rule out that this is partly a product issue as well, not just your pattern.

n8n’s “matches regex” operator in IF nodes expects JavaScript regex syntax, not Python. your pattern abc|def is valid but needs to be wrapped as /abc|def/. try testing in your IF node with the pattern /abc|def/ and it should match abc123. if you’re migrating from older versions, check the n8n changelog for regex behavior changes — there was a shift around 2.11 where they tightened validation. also keep in mind that JS regex is case-sensitive by default, so if your values are mixed-case you might need flags like /abc|def/i.

Thanks both.
Using square brackets make it work:

@Benjamin_Behrens see screenshot above, /abc|def/ doesn’t work either.
I think your comment about adding a /i flag is also worth providing a better documentation on n8n regexes, since there’s also a node option “Ignore case”: which flags are accepted by n8n regexes? Which have precedence over node options? Why are square brackets necessary when they are not in regex101 with flavor Javascript? etc.

False flag @tamy.santos , the square brackets (I think they are to define character sets) are not a solution:

@jb8n

In regex, square brackets defines a character class, so it matches individual characters, not full alternatives like john doe|alice|bob. If you want alternation, I’d use parentheses instead, for example ^(john doe|alice|bob) if you want the string to start with one of those values, or .(john doe|alice|bob). if you want to match them anywhere in the text. So thanks for calling that out — the brackets would definitely change the meaning of the pattern.

Thanks, I tried your suggestions, but adding parentheses doesn’t lead to the expected behavior either:

Does this simple IF node make the regex match pass on your instance?

sorry, my /abc|def/ suggestion was off — n8n’s regex field takes raw patterns without JS slash delimiters. but if abc|def also fails on a value that literally starts with abc, that does look like a real behavior regression between 2.9.x and 2.13.x. at that point i’d open a GitHub issue with the minimal repro (single pattern, known input, exact version) — easier for the team to confirm and track.

Thanks!

That’s indeed a bug, already reported a month ago: | (OR operator) in regex not working in Switch node · Issue #25971 · n8n-io/n8n · GitHub
The pipe (|) character seems to be saved by the UI as a newline, breaking the regex.
It also explains why similar regex with a pipe character are behaving as expected in my older workflows that I didn’t touch in a while.

A workaround mentioned there, that I can confirm works for me, is to set the right operand as expression instead of fixed

1 Like

nice find — a UI serialization bug explains the inconsistency perfectly. good that it’s already tracked. the expression workaround is clean too, it bypasses the field entirely so the raw pattern reaches the engine intact.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.