I’m working on a simple enough task to export data from a publishing pages library into an external database for analysis. The brief was to export the meta data about each page, including all published versions of the pages.
Seems simple enough and away I went with a simple CAML query of:
<Where><Eq><FieldRef Name='_ModerationStatus' /><Value Type='ModStat'>Approved</Value></Eq></Where>
Once I’d retrieved the list items and started iterating through the collection I then hit an exception on the following line:
SPListItemVersionCollection versions = item.Versions;
The exception details were:
Message:Value does not fall within the expected range.
Stack Trace: at Microsoft.SharePoint.SPFieldMap.GetColumnNumber(String strFieldName)
at Microsoft.SharePoint.SPListItemCollection.GetRawValue(String fieldname, Int32 iIndex)
at Microsoft.SharePoint.SPListItem.GetValue(SPField fld, Int32 columnNumber, Boolean bRaw)
at Microsoft.SharePoint.SPListItem.GetValue(String strName, Boolean bThrowException)
at Microsoft.SharePoint.SPListItem.GetValue(String strName)
at Microsoft.SharePoint.SPListItem.DoesUserHavePermissions(SPBasePermissions permissionMask)
at Microsoft.SharePoint.SPListItem.CheckPermissions(SPBasePermissions permissionMask)
Now the bizarre thing was that if I set a breakpoint on the above line, then when paused on the breakpoint if I added a watch on item AND expanded the item in the watch window then the code would work from that point on (classis heisenbug).
I looked through the stack trace in reflector and found the answer – my SPQuery object had a small ViewFields property (I was retrieving just the fields I wanted to archive) and reflector showed that the code was throwing the ArgumentException because the SPListItem was missing the PermMask field. A quick change to my SPQuery.ViewFields so that it included a:
<FieldRef Name='PermMask' />
and everything worked fine, score one more to reflector.
I’d bet there’s many more dark corners in the SharePoint API that have a wee look at the PermMask field, might have to include it in any SPQuery.ViewFields value from now on.