Call doc.closeMIMEEntities after touching doc.getMIMEEntity

Posted on

Another stupid mistake has taken a lot of my time last week. I developed a small library to provide function(s) to move attachments from rich text fields to separate db (nsf or some other). This function was supposed to be part of bigger process, so saving of document being processed was meant to happen in other code. That is why I had not tested what doc.save() would do. My tests were just checking destination db for created records containing moved files. Other part of process was developed by colleague of mine, he tested his part expecting my function to return true or false. And the function was returning true or false. But when his code started to call real implementation of my function, our server crashed with nice and reassuring PANIC: LookupHandle: handle out of range.

At first I was thinking “all tests are green” therefore mistake is not in my code. Stupid, right? But hey, calling just my function did not crash the server.

But the same was true for his part of code.

So we started to track down the exact place where error was by turning on debug logging and adding some more log calls, checking server console and even reading those stack trace logs and heap dumps and I have to tell you these are not easy to read and understand. After a while we were sure trouble is caused by doc.save() call that occurred at the final step of the whole process. And that it crashed the server only if my function was called before.

Ok, that was time to admit I am the one to be blamed. So I started to review code in my library trying to find something that could cause such big trouble to server. I recycled every object, checked all variables for null before accessing them even when I was assigning some hardcoded value to them on the line above…you know the usual desperate stuff you do when you have no idea where the bug is. I would even try black magic, if I know it :-)

I was of course searching internet for help but my problem seemed to be completely new. How I hate when this happens!

Long story short: I was accessing data in fields of type MIME_PART, just reading from them via doc.getMIMEEntity(fieldName). Then I was looping through mimeEntity via getNextEntity looking for attachments and copying them to the destination db. And then I was calling doc.removeItem(fieldName) to remove already processed fields in the document. But I forgot to call doc.closeMIMEEntities(false, fieldName) before calling doc.removeItem. And following doc.save() call crashed the server.

There is code example in documentation. There is no doc.closeMIMEEntities() call. But there is also no doc.save() there and no doc.removeItem().

Moral of the story? Do not read just part of documentation you think is relevant. Read also related info. There is in fact a need of doc.closeMIMEEntities() call mentioned here.

And even if you think you have fulfilled the contract (API we have agreed on) and your code is fine, it in fact could not be true. Writing tests and test driven development in general is extremely helping but even this great approach can not save you from your mistakes. Because it is usually you writing the tests.