I can confirm the behavior you see. I think the exception throws a CF servlet before Application.cfc is thrown, which explains why onError never fires.
So far, the only option that worked for me is to add a custom error page to WEB-INF\web.xml using the HTTP status code:
<error-page> <error-code>400</error-code> <location>/path/to/myErrorPage.cfm</location> </error-page>
Note. From the comments, @Adrian mentioned that he added above to \cfusion\runtime\conf\web.xml , and not the one that was in web-inf\ .
Update 1:
Further reading suggests that you can also set things up on a more narrow level. To handle a specific kind of exception, use <exception-type> instead of <error-code> . For example:
<error-page> <exception-type>java.lang.Exception</exception-type> <location>/path/to/myErrorPage.cfm</location> </error-page>
However, in my (brief) test, CF10 seems to have used very general exception classes for this error. Both have many potential reasons, and not just placing too many form fields. So keep that in mind. Of course, this is a bit more focused than handling all HTTP 500 errors, but it may still cover other reasons.
javax.servlet.ServletException: ROOT CAUSE: java.lang.IllegalStateException: Cannot call sendError() ..
Strike>
Update 2:
Turns out javax.servlet.ServletException was just a red herring. As @AdrianWright noted in the comments, this error is related to debugging options. When the CF generates the message โMaximum number of POST request parametersโ, it incorrectly takes into account debugging, which in turn raises a new exception: java.lang.IllegalStateException . Hence the HTTP 500 error:
When debugging is disabled (as in the production system), CF simply writes the error message directly to the response stream and returns an HTTP 400 status code. Since the exception is not thrown, <exception-type> is useless here. So you are stuck in using a status code:
<error-page> <error-code>400</error-code> <location>/path/to/myErrorPage.cfm</location> </error-page>
However, on the user error page, you can retrieve the error message from the request stream . Then process it accordingly:
<cfset req = getPageContext().getRequest()> <cfset message = req.getAttribute("javax.servlet.error.message")> <cfif message contains "POST parameters exceeds"> Too many form fields. do something... <cfelse> Some other cause. do something else </cfif>