soap-errorstroubleshootingweb-services

SOAP VersionMismatch Fault: How to Fix SOAP 1.1 and 1.2 Envelope Conflicts

SOAPless Team6 min read

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:

VersionContent-TypeAction parameter
SOAP 1.1text/xml; charset=utf-8Separate SOAPAction HTTP header
SOAP 1.2application/soap+xml; charset=utf-8action 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

  1. Capture the raw HTTP request (use a proxy tool like Fiddler, mitmproxy, or Wireshark) and check the Content-Type header and envelope namespace.
  2. Download and inspect the WSDL — look for soap:binding vs. soap12:binding to determine the expected version.
  3. Check both the namespace and Content-Type — fixing one without the other will still trigger the fault.
  4. 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.