You send a perfectly formed SOAP request and the service responds with:
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Body>
<env:Fault>
<env:Code>
<env:Value>env:VersionMismatch</env:Value>
</env:Code>
<env:Reason>
<env:Text xml:lang="en">
Wrong SOAP version used. Expected SOAP 1.1, received SOAP 1.2.
</env:Text>
</env:Reason>
</env:Fault>
</env:Body>
</env:Envelope>
A VersionMismatch fault is one of the few SOAP errors that's unambiguous: the service received a SOAP envelope version it doesn't support. Your client sent SOAP 1.2 to a SOAP 1.1 endpoint, or vice versa. The fix is straightforward once you understand the exact differences between the two versions.
The Two Versions of SOAP
SOAP 1.1 (released 2000) and SOAP 1.2 (released 2003) are not wire-compatible. They differ in three critical areas that directly cause VersionMismatch faults: the envelope namespace, the HTTP Content-Type header, and the way the SOAP action is communicated.
Envelope Namespace
This is the primary identifier a SOAP processor uses to determine the version:
SOAP 1.1:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<!-- operation content -->
</soap:Body>
</soap:Envelope>
SOAP 1.2:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Body>
<!-- operation content -->
</soap:Body>
</soap:Envelope>
If the service is a SOAP 1.1 endpoint and it sees the namespace http://www.w3.org/2003/05/soap-envelope, it immediately rejects the request with a VersionMismatch fault. No further parsing occurs.
Content-Type Header
The HTTP Content-Type header also differs between versions, and many servers validate it before even parsing the XML body:
| Version | Content-Type | Action parameter |
|---|---|---|
| SOAP 1.1 | text/xml; charset=utf-8 | Separate SOAPAction HTTP header |
| SOAP 1.2 | application/soap+xml; charset=utf-8 | action parameter in Content-Type |
Sending application/soap+xml to a SOAP 1.1 service can trigger the mismatch error at the HTTP level before the XML is even inspected.
SOAPAction vs. action Parameter
In SOAP 1.1, the action is communicated via a dedicated HTTP header:
POST /service.asmx HTTP/1.1
Host: api.example.com
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://example.com/GetOrder"
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
...
</soap:Envelope>
In SOAP 1.2, the action is embedded in the Content-Type header:
POST /service.svc HTTP/1.1
Host: api.example.com
Content-Type: application/soap+xml; charset=utf-8; action="http://example.com/GetOrder"
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
...
</soap:Envelope>
How to Determine the Expected Version from the WSDL
Before fixing your code, you need to know which version the service expects. The WSDL tells you this explicitly through the binding's transport namespace.
WSDL Indicator for SOAP 1.1
<wsdl:binding name="OrderServiceSoap" type="tns:OrderServiceSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document" />
<!-- namespace prefix "soap" maps to http://schemas.xmlsoap.org/wsdl/soap/ -->
</wsdl:binding>
The soap:binding element uses the namespace http://schemas.xmlsoap.org/wsdl/soap/ — this means SOAP 1.1.
WSDL Indicator for SOAP 1.2
<wsdl:binding name="OrderServiceSoap12" type="tns:OrderServiceSoap">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document" />
<!-- namespace prefix "soap12" maps to http://schemas.xmlsoap.org/wsdl/soap12/ -->
</wsdl:binding>
The soap12:binding element uses the namespace http://schemas.xmlsoap.org/wsdl/soap12/ — this means SOAP 1.2.
Some WSDLs define both bindings. In that case, the service supports both versions, and you need to use the correct endpoint URL for each version.
Fixing the Version Mismatch
In curl (for testing)
SOAP 1.1 request:
curl -X POST https://api.example.com/service.asmx \
-H "Content-Type: text/xml; charset=utf-8" \
-H 'SOAPAction: "http://example.com/GetOrder"' \
-d '<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetOrder xmlns="http://example.com/">
<orderId>12345</orderId>
</GetOrder>
</soap:Body>
</soap:Envelope>'
SOAP 1.2 request:
curl -X POST https://api.example.com/service.svc \
-H 'Content-Type: application/soap+xml; charset=utf-8; action="http://example.com/GetOrder"' \
-d '<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Body>
<GetOrder xmlns="http://example.com/">
<orderId>12345</orderId>
</GetOrder>
</soap:Body>
</soap:Envelope>'
In Python (zeep)
from zeep import Client, Settings
from zeep.transports import Transport
# zeep auto-detects the version from the WSDL binding
client = Client("https://api.example.com/service?wsdl")
# If the WSDL has both SOAP 1.1 and 1.2 bindings,
# select the correct one explicitly:
client_1_2 = Client(
"https://api.example.com/service?wsdl",
service_name="OrderService",
port_name="OrderServiceSoap12"
)
In Java (JAX-WS)
import javax.xml.ws.BindingProvider;
import javax.xml.ws.soap.SOAPBinding;
OrderService service = new OrderService();
OrderServiceSoap port = service.getOrderServiceSoap12(); // Use the 1.2 port
// Verify the binding
SOAPBinding binding = (SOAPBinding) ((BindingProvider) port).getBinding();
// binding will use SOAP 1.2 protocol automatically
In .NET (WCF)
<!-- For SOAP 1.1, use basicHttpBinding -->
<endpoint binding="basicHttpBinding" contract="IOrderService" />
<!-- For SOAP 1.2, use wsHttpBinding or customBinding -->
<endpoint binding="wsHttpBinding" contract="IOrderService" />
If you need explicit control over the SOAP version in a custom binding:
<customBinding>
<binding name="Soap12Binding">
<textMessageEncoding messageVersion="Soap12" />
<httpTransport />
</binding>
</customBinding>
In Node.js (soap npm package)
const soap = require("soap");
// Force SOAP 1.2
const options = {
forceSoap12Headers: true,
};
soap.createClient(wsdlUrl, options, (err, client) => {
// client will use SOAP 1.2 envelope namespace
// and application/soap+xml Content-Type
client.GetOrder({ orderId: "12345" }, (err, result) => {
console.log(result);
});
});
Fault Structure Differences
Even the fault format differs between SOAP versions, which can confuse error-handling code:
SOAP 1.1 Fault:
<soap:Fault>
<faultcode>soap:VersionMismatch</faultcode>
<faultstring>Version mismatch</faultstring>
<detail>Expected SOAP 1.1</detail>
</soap:Fault>
SOAP 1.2 Fault:
<env:Fault>
<env:Code>
<env:Value>env:VersionMismatch</env:Value>
<env:Subcode>
<env:Value>rpc:BadArguments</env:Value>
</env:Subcode>
</env:Code>
<env:Reason>
<env:Text xml:lang="en">Version mismatch</env:Text>
</env:Reason>
<env:Detail>
<ErrorInfo>Expected SOAP 1.2</ErrorInfo>
</env:Detail>
</env:Fault>
SOAP 1.2 uses a structured Code/Subcode hierarchy instead of the flat faultcode string. If your error-handling code parses faultcode but the response is SOAP 1.2, you'll miss the error details entirely.
Quick Diagnostic Steps
- Capture the raw HTTP request (use a proxy tool like Fiddler, mitmproxy, or Wireshark) and check the Content-Type header and envelope namespace.
- Download and inspect the WSDL — look for
soap:bindingvs.soap12:bindingto determine the expected version. - Check both the namespace and Content-Type — fixing one without the other will still trigger the fault.
- Look for dual-binding WSDLs — if the WSDL exposes both versions, make sure you're hitting the right endpoint URL for the version you're sending.
How SOAPless Helps
SOAP version mismatches are one of the most common integration headaches, especially when consuming third-party services where you don't control the server configuration. SOAPless eliminates this friction entirely.
When you register a WSDL with SOAPless, the platform automatically detects whether the upstream service uses SOAP 1.1 or 1.2. It reads the binding namespace from the WSDL and constructs requests with the correct envelope namespace, Content-Type header, and action format. Your application simply makes a REST JSON call — no XML construction, no version-specific headers, no Content-Type guesswork.
SOAPless also generates an OpenAPI specification for each registered service, so you can explore available operations and test them directly from the dashboard before writing a single line of integration code.