Some time ago during migrating of the content from old Sharepoint 2007 site to O365 we faced with the following problem: some document libraries in SP 2007 environment had 2 fields with different titles and internal names, but with the same ids. Most probably it was error in one of the custom solution deployed to old site. But because of that problem migration tool could not copy content from such document libraries. Further investigation showed that one of fields with duplicated id is not really used in documents metadata, so it was decided to delete it from doclibs in order to proceed with migration.
I quickly wrote simple utility (remember that source environment was SP2007 where we lived with console utilities instead of PowerShell scripts) which iterates through all sites and lists and checks for duplicated fields. When they are found it deletes field with specified title:
It worked properly on test lists created manually, i.e. manually added field was successfully removed by the code above. However on production situation was more complicated: fields were added by content types (although problematic field was not in any bound content types. Probably when developers found the error they removed field from content types, but it stay in provisioned doclibs) and attempt to run the above code there caused exception:
Operation is not valid due to the current state of the object
which was thrown from line 27, i.e. list.Fields.Delete() method. In order to avoid the error I checked implementation of that method in Reflector:
As shown above InvalidOperationException (exactly for which error message “Operation is not valid …” is displayed for end users) is thrown on line 16 if SPField.CanBeDeleted property of the deleting field is false. Let’s check this property also:
This is readonly property. However internally it uses another property bool? AllowDeletion which has setter. By default it was null for deleted fields, so in order to avoid the InvalidOperationException I modified the console utility code and added setting of AllowDeletion property to true before to delete the field from list’s fields collection:
Additional lines are 26-31. After that code successfully deleted field with duplicated id and it became possible to migrate the content from all document libraries.