Wednesday, January 20th, 2010

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

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.

{ 11 comments… read them below or add one }

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()….

Reply

Veera January 20, 2010 at 8:50 pm

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

Reply

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 ^

Reply

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.

Reply

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.

Reply

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.

Reply

thizz October 29, 2010 at 4:26 pm

thx you saved a lot of my time

Reply

Philon April 27, 2011 at 5:54 pm

dudes,

String oldPattern = Pattern.quote( aOldPattern );
String newPattern = Matcher.quoteReplacement( aNewPattern );
return aInput.replaceAll( oldPattern, newPattern );

Reply

Veera April 28, 2011 at 11:59 am

that should word.

Reply

Ali Hammad October 14, 2011 at 5:11 pm

Thank you very much Veera, that solved my problem. A huge string that may take a whole day to find the error. I just removed $ and its working, wow, what a fail:P

Reply

Raghavan alias Saravanan M October 15, 2011 at 3:02 pm

A good post!

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

Well said :)

Reply

Leave a Comment

Previous post:

Next post: