This is not actually a gotcha in Grails but more a gotcha in my domain class. However, it seems like it might be a common enough scenario to trip up someone else.
I have a domain class which I am populating from an uploaded Excel spreadsheet. Each row in the spreadsheet corresponds to a new instance of the domain class. Since I anticipate that my users will try to upload spreadsheets with errors in some of the rows (not pessimistic, just realistic), I want my app to accept all rows that are properly formatted and provide useful error messages for the rows that are not. I created a spreadsheet that exercised all of my error cases and ran into an unexpected outcome: every time I uploaded the spreadsheet I got duplicates of all of the valid rows in the spreadsheet.
This was surprising because I was using the query by example facilities to check and see if the row was a duplicate. Despite not changing the spreadsheet between uploads, I was still getting duplicates. Then it dawned on me--I had a Date created = new Date() field in my domain class to keep track of when the domain class was created. Simply adding an example.created = null to my query example solved the problem.
Like I said in the opening paragraph, not a gotcha in Grails. The query by example stuff works exactly how I expect it to, you just have to watch out about initialized fields.