John, hosting the Esri sample is a brilliant idea. I grabbed the code and put in on my server. It worked just fine, just like the Esri hosted sample. I modified the print URL to point to my export service and I got a different error (a timeout). So it does appear that there is some issue with my local print service. Anyway, I went back to my app code and changed it to the Esri hosted export service, like in the sample code, but I still get the "Error code:400". I pointed the Esri sample code to my proxy, and the sample still works, so I assume my proxy is not the problem?
I checked the network traffic and my app does show an execute request (GET) to the Esri export service with a wait time of 643ms and a response of 200ms. The working sample code shows a similar request with a wait time of 2.49s and a response time of 200ms. So it looks like there is communication, but maybe there is a parameter in my map that the export service doesn't like? I can't find anything that appears out of sorts.
I changed the sample code to point to JSAPI 3.4, like my app, and the sample still works. I've gradually been fiddling with each code set to get them to look as similar as possible, but the result is still that the sample works just fine and my app keeps throwing the error. This probably means I am missing some little inconsistency in my app code. The main difference I can see in my app is that it is still using the "legacy" module requires and the sample is using the AMD module requires. I guess maybe I need to take the leap and just update all of my code to use the AMD style.
Any additional guidance is much appreciated.