[Update: Microsoft has tentatively scheduled a fix for this in the March 2015 CU]
Within a client's document libraries we have found that fields which were once set to be required mysteriously become optional, on the default content type, over time.
It turns out that this occurs during innocent field updates. One can run into it very easily if using more than one content type in a library. The issue affects both SharePoint 2010 and 2013, both on-premise and on Office 365.
It occurs regardless of how the column is updated. Anything that initiates a list field update on that column breaks it. That includes setting a default value, adding the column as a metadata filter column and setting a taxonomy field anchor. In fact, simply clicking the save button in the field settings page will do it, even if no changes are made. Updating the field via code causes the same problem.
Field attributes on a document library that has content types are represented at multiple levels.
Column definition in the site
Column definition in the list
Field link definition in the site content type
Field link definition in the list content type
Suppose an update is executed on the column definition in the list, as illustrated in the screen grab further above. Such an update copies the "Required" attribute value over the corresponding value in the field link of the default (first) list content type.
What value will be copied? Here comes the twist. If more than one content type exists in the library the value FALSE will always be used. This can be explained as follows.
There is a subtle change in the field settings page once a second content type is added to the list.
When 1 content type is used
|When more than 1 content type is used|
Notice how the "Required" attribute is no longer available. It is still set to FALSE behind the scenes, however, so clicking the Save button on this page picks up the underlying FALSE value and copies it down to the corresponding field link on the default content type. The same copying occurs if a call to Update() is made via code. The following picture illustrates what's happening.
If you think about it, hiding the attribute in the UI does kind-of make sense. Once we have more than one content type, we may want the field to be required in some content types but optional in others. So Microsoft hides that part of the field settings at list level and assumes we'll go set that value in each list content type. The buggy part is the fact that future updates on the list field setting overwrite what we do at list content type level, rather than just leaving that attribute alone.
If you need the field to remain mandatory across all the list content types, change the "Required" attribute at list column level to "Yes"
before adding a second content type to the list. This locks that value in the list field schema and thereafter, no matter how many content types you've added, the TRUE value will always be copied down to them when field updates are triggered.
Alternatively, use PowerShell to retrieve the list field and set its "Required" attribute to true. Happily, this can be done even after multiple content types exist in the library.
In either case, this need be done only once in the library's lifetime and it will remain "fixed" thereafter.
There is a caveat. If you need the field to be required in some content types and optional in others, and also need a specific content type to be the default one, this is not easy to control. Whenever a list field update is triggered, the value will be copied down over the default content type. All you can do is influence whether that source value is locked at TRUE or FALSE.