このエラーは WCF 側でよく出るもので、意味としては「受け取った XML body が契約どおりではなかった」です。
The formatter threw an exception while trying to deserialize the message
さらに詳細で次のような文言が出ることもあります。
There was an error while trying to deserialize parameter
この場合、失敗している parameter を起点に見るのが最短です。
主な原因
- wrapper 要素名が違う
- namespace URI が違う
- primitive のはずが object になっている
- 配列と単体要素の形がずれている
- optional / nillable の扱いが契約と違う
wrapper mismatch の例
期待されている形:
<tns:GetCustomer xmlns:tns="http://example.com/contracts">
<tns:id>42</tns:id>
</tns:GetCustomer>
実際に送っている形:
<GetCustomerRequest xmlns="http://example.com/contracts">
<id>42</id>
</GetCustomerRequest>
これだけでも formatter exception は起こります。
切り分け方
最小リクエストから始めて、1 フィールドずつ足してください。
curl -s https://example.com/service.svc?wsdl -o service.wsdl
次を重点的に見ます。
- operation 要素名
- parameter の順序
- 子要素の namespace
- 配列か単体か
SoapUI では通るのにアプリでは落ちる場合、SoapUI の raw request と diff を取るのが最短です。
配列と scalar のズレ
JSON から XML を手で組み立てる時に起きがちです。
期待:
<tns:tags>
<tns:string>red</tns:string>
<tns:string>blue</tns:string>
</tns:tags>
実際:
<tns:tags>red</tns:tags>
見た目は近くても契約としては別物です。
shell ベースの確認
curl -v https://example.com/service.svc \
-H 'Content-Type: text/xml; charset=utf-8' \
--data @request.xml
コードを触る前に raw XML で再現させると、ライブラリ由来のノイズが消えます。
このエラーが複数のジョブやスクリプトで繰り返し出るなら、XML の責務をアプリごとに持たせない構成に寄せた方が再発を減らせます。