CF definitely did manage to receive and processe the request, because there are a bunch of cfhttp requests that would only be run if the CF code in question are executed, and we know the cfhttp requests definitely did run because our custom logging routine logged all the relevant details.
Yes it's a weird one, and I've found the culprit - I forgot to encode the xml string before sending it with the ajax request. And for some reason, if you do that, the server would still process the request (albeit with the form being completely blank), but respond with a 400 error at the end of it.
Here's a simple test to replicate this behavior:
var url = "http://localhost/test.cfm";
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
console.log(xhr.status);
console.log(xhr.responseText);
}};
var data = "blah=1&xml=<company><![CDATA[blah & blah]]></company>";
xhr.send(data);