Page protection violation: This may be caused by manual alteration of protected page items. If you are unsure what caused this error, please contact the application administrator for assistance. Contact your application administrator.
What made this problem even more interesting was that Tom could reproduce it only occasionally and I could not reproduce it. The application logic in AskTom has remained essentially unchanged for a number of years. The only thing that this could be related to was a bug in Application Express 4.1.1, right? Since AskTom runs on apex.oracle.com (much to the chagrin of some), and apex.oracle.com was upgraded to Application Express 4.1.1 in February 2012, this must be the source of the problem.
Well...the answer is yes and no. Certainly, in February 2012, apex.oracle.com was upgraded to Oracle Application Express 4.1.1. And it is this changed behavior that Tom was running into. But the reason for it is enhanced functionality in Application Express 4.1.1.
If you look at the source of a page from Application Express 4.1.1, towards the bottom of the page you'll see something like
<input name="p_page_checksum" type="hidden" value="577060F3783D7C8508474077662A80DE" />
This occurs right before the closing </form> tag. This is a checksum value computed against selected items on a page. When the page is submitted, APEX compares the checksum value to confirm the integrity of the page and these selected items on it. In Tom's case, he was 1) in London on business travel, not on a super fast network, and 2) he was editing a relatively large page (792 KB). The fundamental problem - he was submitting the page before the page had fully rendered, meaning the page_checksum_value was absent from the page. The temporary workaround I suggested to Tom was "wait a few seconds" - at least for large pages like this one. Fortunately, large pages like this are the exception for him. We could get fancy by disabling the buttons until the page had fully rendered, via a dynamic action.
I have also seen a similar issue crop up for customers who were lacking the #FORM_CLOSE# substitution in their page template. Since this page_checksum_value is anchored to the tag, if there is no #FORM_CLOSE#, then there is no page checksum value either.