java.lang.IllegalArgumentException: Illegal group reference in String.replaceAll

by Veera on January 20, 2010

in Java

I was working on an internal project that is used for archiving user’s blog posts. I released this application to an internal community and it was recieved quite well by the users. I made sure that the code was bug free, as far as I tested it and the code was working as expected with out any serious issues. But what is an application when there is no bug in it?

One user got back to me saying that the code successfully downloaded the blog posts but it failed during the index building process. The index building process was doing a simple string replacement, replacing a pattern with the list of archived posts links. I was using String.replaceAll() method for this. The user reported back that he is getting the exception: java.lang.IllegalArgumentException: Illegal group reference.

Initially I was clueless about why it is throwing the exception. But later when I debugged the code, I found that the exception was thrown because of the $ symbols that were present in the parameters to the replaceAll() method. To make it clear, have a look at the below code:

public static void main(String args[]) throws Exception {
    String template = "The user has spent amount in a day";
    String pattern = "amount";
    String output = template.replaceAll(pattern, "$ 100");
    System.out.println(output);
}

If you think that the above code will run without a issue and print “The use has spent $ 100 in a day”, then you are wrong. Here’s what this code will spit out:

Exception in thread "main" java.lang.IllegalArgumentException: Illegal group reference
        at java.util.regex.Matcher.appendReplacement(Matcher.java:713)
        at java.util.regex.Matcher.replaceAll(Matcher.java:813)
        at java.lang.String.replaceAll(String.java:2190)
        at demo.BugDemo.main(BugDemo.java:16)
Java Result: 1

The exception is thrown because the replacement string (i.e. “$ 100″) contains a $ symbol in it. And the Matcher.appendReplacement() class internally uses the $ symbol as a identifier for grouping. So inorder to avoid this, the $ symbol in the replacement string needs to be escaped using \\$. So after this fix, the correct code for the above program would be:

String output = template.replaceAll(pattern, "\\$ 100");

Hm.. perfect. This incident reminds me that debugging can teach us a lot than the actual development.

Related Articles (System generated)

Follow me on Twitter to get notified whenever I update this blog.

{ 6 comments }

Mohammed Yousuff January 20, 2010 at 7:02 PM

Good one. I believe String class should say the same docs as it was in Matcher.replaceAll() which is added in string.replaceAll()….

Veera January 20, 2010 at 8:50 PM

agreed. Otherwise it is little difficult to figure it out why the replaceAll() method fails.

JB January 21, 2010 at 5:18 AM

Yes, debugging teaches a few lessons.

I thought it was due to $ being a regex symbol. Pardon me, I am not a Java programmer, but know javascripting.

java.util.regex namespace gave me solace :-)

Did you try with other regex symbols like ^

Veera January 21, 2010 at 8:07 AM

I haven’t tested the code for other regex symbols, but I guess those symbols also should be escaped.

Sreenivas January 25, 2010 at 10:02 AM

Veera, the replaceAll method takes in regular expressions as the parameter and ‘$’ in regex is a special character that represents end of a line.

Grouping, on the other hand is done using parantheses.

Veera January 25, 2010 at 12:10 PM

according to the API documentation of Matcher.appendReplacement method,

The replacement string may contain references to subsequences captured during the previous match: Each occurrence of $g will be replaced by the result of evaluating group(g).

and that’s what I meant by grouping.

Comments on this entry are closed.

Previous post:

Next post: