function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
jhartjhart 

Summer '13 bug: Attachment.BodyLength null in "before insert" triggers

Our "Absolute Automation" app logs emails and their attachments to salesforce.

One of our configurable features is the ability to skip attachments based on extension or file size.

As there are multiple ways that Attachments are logged (Email Services or the normal CRUD API), we implemented this "attachment skipping" feature via a "before insert" trigger on Attachments.

The trigger, simplified, looks like this:

 

trigger AttachmentFilter on Attachment bulk (before insert) {
  for (Attachment a : Trigger.new) {
    if (a.BodyLength < CONFIGURED_SIZE) a.addError('Skipping attachment per SIZE_TOO_SMALL');
    }
  }

This has worked great for awhile now.

However, as of Summer '13, it no longer works.  Why?  Because the "BodyLength" field is now _NULL_ in the trigger context.  This happens both when inserting Attachments via the SOAP API as well as in Apex Tests that insert them directly.

If we modify our trigger like so:

 

trigger AttachmentFilter on Attachment bulk (before insert) {
  System.debug('AttachmentFilter, input is: ' + Trigger.new);
  for (Attachment a : Trigger.new) {
    if (a.BodyLength < CONFIGURED_SIZE) a.addError('Skipping attachment per SIZE_TOO_SMALL');
    }
  }

 We can verify that BodyLength is null for all Attachments in Trigger.new, even though "Body" is not.

Here's the debug output taken from a run of Apex testMethods:

 

16:07:26.074 (7074859000)|USER_DEBUG|[2]|DEBUG|
AttachmentFilter, input is: (
Attachment:{Body=Blob[2],    ... Name=oktxt.yada,        ... Id=null, BodyLength=null, ContentType=text/plain},
Attachment:{Body=Blob[2048], ... Name=okbig.yada,        ... Id=null, BodyLength=null, ContentType=image/yada},
Attachment:{Body=Blob[2],    ... Name=no_small.yada,     ... Id=null, BodyLength=null, ContentType=image/yada},
Attachment:{Body=Blob[2],    ... Name=no_small.gif,      ... Id=null, BodyLength=null, ContentType=IMAGE/gif},
Attachment:{Body=Blob[2],    ... Name=no_isfoo.FOO,      ... Id=null, BodyLength=null, ContentType=text/plain},
Attachment:{Body=Blob[2],    ... Name=no_isfoo.yada.foo, ... Id=null, BodyLength=null, ContentType=text/plain},
Attachment:{Body=Blob[2048], ... Name=no_isjpg.jPg,      ... Id=null, BodyLength=null, ContentType=image/yada})

16:07:26.309 (7309998000)|USER_DEBUG|[2]|DEBUG|
AttachmentFilter, input is: (
Attachment:{Body=Blob[2],    ... Name=oktxt.yada,        ... Id=null, BodyLength=null, ContentType=text/plain},
Attachment:{Body=Blob[2048], ... Name=okbig.yada,        ... Id=null, BodyLength=null, ContentType=image/yada},
Attachment:{Body=Blob[2],    ... Name=no_small.yada,     ... Id=null, BodyLength=null, ContentType=image/yada},
Attachment:{Body=Blob[2],    ... Name=no_small.gif,      ... Id=null, BodyLength=null, ContentType=IMAGE/gif})

16:07:30.363 (11363893000)|USER_DEBUG|[2]|DEBUG|
AttachmentFilter, input is: (
Attachment:{Body=Blob[2],    ... Name=oktxt.yada,        ... Id=null, BodyLength=null, ContentType=text/plain},
Attachment:{Body=Blob[2048], ... Name=okbig.yada,        ... Id=null, BodyLength=null, ContentType=image/yada})

16:07:30.493 (11493729000)|USER_DEBUG|[2]|DEBUG|
AttachmentFilter, input is: (
Attachment:{Body=Blob[2],    ... Name=no_isfoo.FOO,      ... Id=null, BodyLength=null, ContentType=text/plain},
Attachment:{Body=Blob[2],    ... Name=no_isfoo.yada.foo, ... Id=null, BodyLength=null, ContentType=text/plain},
Attachment:{Body=Blob[2048], ... Name=no_isjpg.jPg,      ... Id=null, BodyLength=null, ContentType=image/yada})

16:07:30.565 (11565822000)|USER_DEBUG|[2]|DEBUG|
AttachmentFilter, input is: (
Attachment:{Body=Blob[2],    ... Name=no_small.yada,     ... Id=null, BodyLength=null, ContentType=image/yada},
Attachment:{Body=Blob[2],    ... Name=no_small.gif,      ... Id=null, BodyLength=null, ContentType=IMAGE/gif})

16:07:30.626 (11626327000)|USER_DEBUG|[2]|DEBUG|
AttachmentFilter, input is: (
Attachment:{Body=Blob[2],    ... Name=oktxt.yada,        ... Id=null, BodyLength=null, ContentType=text/plain},
Attachment:{Body=Blob[2048], ... Name=okbig.yada,        ... Id=null, BodyLength=null, ContentType=image/yada})

16:07:30.710 (11710629000)|USER_DEBUG|[2]|DEBUG|
AttachmentFilter, input is: (
Attachment:{Body=Blob[2],    ... Name=no_isfoo.FOO,      ... Id=null, BodyLength=null, ContentType=text/plain},
Attachment:{Body=Blob[2],    ... Name=no_isfoo.yada.foo, ... Id=null, BodyLength=null, ContentType=text/plain},
Attachment:{Body=Blob[2048], ... Name=no_isjpg.jPg,      ... Id=null, BodyLength=null, ContentType=image/yada})

16:07:30.719 (11719401000)|USER_DEBUG|[2]|DEBUG|
AttachmentFilter, input is: (
Attachment:{Body=Blob[2],    ... Name=no_small.yada,     ... Id=null, BodyLength=null, ContentType=image/yada},
Attachment:{Body=Blob[2],    ... Name=no_small.gif,      ... Id=null, BodyLength=null, ContentType=IMAGE/gif})

 

 

 

Salesforce support: I have opened case 09406443 to track this issue.

Best Answer chosen by Admin (Salesforce Developers) 
jhartjhart

Salesforce support tells me the bug has been fixed & will be deployed with the Winter '13 release.

 

Until then, the workaround is switching to use an "after insert" trigger.

All Answers

Avidev9Avidev9
The trigger runs on "before insert", ,and these values are only accessible in after event.
So I guess you need to switch the event to "after insert"
jhartjhart
Normally I might agree with you, but this worked perfectly prior to the Summer '13 release. SFDC support has reproduced the bug and (hopefully) will be working on a regression fix.
jhartjhart
Note - changing the trigger to an "after" trigger does workaround the underlying bug. Thanks for Avi for pointing out the possibility.
jhartjhart

Salesforce support has reproduced the bug, and tells me this:

I am going to escalate this case to back line team and I will update you once I escalated this one.

jhartjhart

Salesforce support tells me the bug has been fixed & will be deployed with the Winter '13 release.

 

Until then, the workaround is switching to use an "after insert" trigger.

This was selected as the best answer