Skip to content

SOAP Fault Detail — Understanding Error Reporting in SOAP Messages

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about SOAP Fault Detail. We cover key concepts, practical examples, and best practices to help you master this topic.

SOAP Faults are error-reporting elements within the SOAP Body that provide structured error information through faultcode, faultstring, faultactor, and detail sub-elements.

What You'll Learn

  • The structure of a SOAP Fault
  • Standard fault codes and their meanings
  • How to create and handle SOAP Faults

Why It Matters

SOAP provides a standard way to communicate errors, unlike REST where error formats are arbitrary. Understanding SOAP Faults is essential for debugging SOAP integrations and building production-ready SOAP services.

Standard Fault Codes

SOAP_FAULT_CODES = {
    '1.1': {
        'VersionMismatch': 'soap:VersionMismatch',
        'MustUnderstand': 'soap:MustUnderstand',
        'Client': 'soap:Client',
        'Server': 'soap:Server'
    },
    '1.2': {
        'VersionMismatch': 'http://www.w3.org/2003/05/soap-envelope/VersionMismatch',
        'MustUnderstand': 'http://www.w3.org/2003/05/soap-envelope/MustUnderstand',
        'Sender': 'http://www.w3.org/2003/05/soap-envelope/Sender',
        'Receiver': 'http://www.w3.org/2003/05/soap-envelope/Receiver'
    }
}

def create_soap_fault(version, code, message, actor=None, detail=None):
    """Create a SOAP Fault response"""
    ns = 'http://schemas.xmlsoap.org/soap/envelope/' if version == '1.1' else 'http://www.w3.org/2003/05/soap-envelope'
    fault_code = SOAP_FAULT_CODES[version].get(code, f'soap:{code}')

    fault = f'<soap:Fault xmlns:soap="{ns}">\n'

    if version == '1.1':
        fault += f'  <faultcode>{fault_code}</faultcode>\n'
        fault += f'  <faultstring>{message}</faultstring>\n'
        if actor:
            fault += f'  <faultactor>{actor}</faultactor>\n'
    else:
        fault += f'  <soap:Code>\n    <soap:Value>{fault_code}</soap:Value>\n  </soap:Code>\n'
        fault += f'  <soap:Reason>\n    <soap:Text xml:lang="en">{message}</soap:Text>\n  </soap:Reason>\n'
        if actor:
            fault += f'  <soap:Node>{actor}</soap:Node>\n'

    if detail:
        fault += f'  <detail>\n{detail}\n  </detail>\n'

    fault += '</soap:Fault>'
    return fault

Fault Handling

import xml.etree.ElementTree as ET

def parse_soap_fault(xml_string):
    """Parse a SOAP Fault into a structured error"""
    root = ET.fromstring(xml_string)
    version = '1.2' if 'http://www.w3.org/2003/05/soap-envelope' in xml_string else '1.1'
    ns = {'s': 'http://schemas.xmlsoap.org/soap/envelope/' if version == '1.1' else 'http://www.w3.org/2003/05/soap-envelope'}

    fault_info = {}

    if version == '1.1':
        faultcode = root.find('.//s:faultcode', ns)
        faultstring = root.find('.//s:faultstring', ns)
        faultactor = root.find('.//s:faultactor', ns)
        detail = root.find('.//s:detail', ns)

        fault_info = {
            'code': faultcode.text if faultcode is not None else None,
            'message': faultstring.text if faultstring is not None else None,
            'actor': faultactor.text if faultactor is not None else None,
            'detail': ET.tostring(detail, encoding='unicode') if detail is not None else None
        }
    else:
        code = root.find('.//s:Code/s:Value', ns)
        reason = root.find('.//s:Reason/s:Text', ns)
        node = root.find('.//s:Node', ns)
        detail = root.find('.//s:Detail', ns)

        fault_info = {
            'code': code.text if code is not None else None,
            'message': reason.text if reason is not None else None,
            'actor': node.text if node is not None else None,
            'detail': ET.tostring(detail, encoding='unicode') if detail is not None else None
        }

    return fault_info

Application-Specific Faults

def create_business_fault(error_code, error_message, details):
    """Create an application-specific SOAP Fault"""
    detail_xml = f'''
    <ns:ErrorDetails>
      <ns:ErrorCode>{error_code}</ns:ErrorCode>
      <ns:ErrorMessage>{error_message}</ns:ErrorMessage>
      <ns:Timestamp>{datetime.utcnow().isoformat()}Z</ns:Timestamp>
    </ns:ErrorDetails>
    '''
    return create_soap_fault('1.1', 'Server', 'Application error occurred', detail=detail_xml)

# Example: validation fault
def create_validation_fault(validation_errors):
    errors_xml = '\n'.join([
        f'    <ns:ValidationError>\n'
        f'      <ns:Field>{err["field"]}</ns:Field>\n'
        f'      <ns:Message>{err["message"]}</ns:Message>\n'
        f'    </ns:ValidationError>'
        for err in validation_errors
    ])
    return create_business_fault('VALIDATION_ERROR', 'Request validation failed', errors_xml)

Common Mistakes

1. Using HTTP Status Codes Instead of SOAP Faults

A SOAP service should return HTTP 200 (for SOAP 1.1) or 500 (for SOAP 1.2) with a SOAP Fault body, not non-standard HTTP status codes.

2. Generic Fault Messages

Returning "Server error" without details makes debugging difficult. Include meaningful faultstring and detail elements.

3. Not Using Standard Fault Codes

Custom fault codes should use standard prefixes (Client, Server, VersionMismatch, MustUnderstand). Non-standard codes may not be recognized by SOAP clients.

4. Exposing Internal Details

The detail element is for application-level errors. Do not expose stack traces or internal paths. Use sanitized error messages.

5. Forgetting the Fault Element Namespace

The Fault element and its children must be in the SOAP envelope namespace. Missing namespace breaks fault Parsing.

Practice Questions

  1. What are the standard SOAP fault codes?
  2. What is the difference between soap:Client and soap:Server faults?
  3. What is the detail element used for?
  4. What HTTP status does a SOAP 1.1 fault return?
  5. How do SOAP 1.2 faults differ from 1.1?

Answers

  1. VersionMismatch, MustUnderstand, Client/Server (1.1) or Sender/Receiver (1.2). 2. Client errors are the sender's fault; Server errors are the receiver's fault. 3. Application-specific error details. 4. 200 OK (with Fault in body). 5. 1.2 uses Code/Reason/Detail structure instead of faultcode/faultstring.

Challenge

Build a SOAP fault handling library that: creates standard-compliant Fault responses, parses Faults from both SOAP 1.1 and 1.2, handles application-specific error details, and provides helpful error messages for common fault codes.

FAQ

What is a SOAP Fault?

A structured error element within the SOAP Body that reports processing errors.

What does soap:Client mean?

The error is caused by the client (e.g., invalid request, missing parameters).

What does soap:Server mean?

The error is caused by the server (e.g., database failure, configuration issue).

What is the detail element for?

Application-specific error details beyond the standard fault information.

How do SOAP 1.1 and 1.2 faults differ?

1.2 uses Code/Reason/Detail structure; 1.1 uses faultcode/faultstring/faultactor/detail.

Mini Project

Build a SOAP error handling middleware that: catches exceptions and converts them to proper SOAP Faults, logs fault details for debugging, sanitizes error messages to avoid leaking internals, and supports both SOAP 1.1 and 1.2 fault formats.

What's Next

  • Learn about WSDL structure for service description
  • Explore WSDL abstract definitions (types, messages, portTypes)
  • Continue to WSDL concrete bindings for SOAP over HTTP

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro