ONVIFOperationException
Bases: Exception
Enhanced exception wrapper for ONVIF operation failures.
This exception provides detailed error information including operation name, error category, SOAP fault details, and the original exception.
It categorizes errors into three types: SOAP, Protocol, and Application errors.
Attributes:
| Name | Type | Description |
|---|---|---|
operation |
str
|
Name of the ONVIF operation that failed |
original_exception |
Exception
|
The underlying exception that was raised |
Version History
- Available since
>=v0.0.1(first release).
Error Categories
SOAP Error
Device returned a SOAP fault (e.g., ActionNotSupported):
- Includes fault code, subcode, message, and detail
- Supports both SOAP 1.1 and 1.2 formats
-
Extracts readable information from XML fault details
Common SOAP Fault Subcodes
ActionNotSupported: Operation not implemented by deviceNotAuthorized: Authentication failed or insufficient permissionsInvalidArgVal: Invalid parameter valueOperationProhibited: Operation not allowed in current stateSender: Client-side error in requestReceiver: Server-side error in device
Protocol Error
Network/HTTP transport failed:
- Connection errors, timeouts, SSL errors
- HTTP status errors (404, 401, 500, etc.)
- DNS resolution failures
Application Error
Generic/unexpected errors:
- Python exceptions, type errors, etc.
- Fallback category for uncategorized errors
Example Error Messages
SOAP Error - Action Not Supported
ONVIF operation 'GetImagingSettings' failed: SOAP Error: code=Receiver, subcode=ActionNotSupported, msg=Optional Action Not Implemented
SOAP Error - Invalid Argument
ONVIF operation 'SetVideoEncoderConfiguration' failed: SOAP Error: code=Sender, subcode=InvalidArgVal, msg=Invalid resolution, detail=Width=1920, Height=1080
Protocol Error - Connection Timeout
ONVIF operation 'GetCapabilities' failed: Protocol Error: HTTPConnectionPool(host='192.168.1.100', port=80): Read timed out.
Application Error - Missing Argument
Notes
- Always wraps the original exception for full error context
- Preserves stack trace through exception chaining
- Extracts maximum information from SOAP fault details
- Handles both
lxml.etree.QNameobjects and strings in subcodes - Safe handling of missing or malformed fault information
- Compatible with Python exception handling best practices
See Also
Error Handlers: Utilities for handling specific error typeszeep.exceptions.Fault: Base SOAP fault exceptionrequests.exceptions.RequestException: Base HTTP error
Source code in onvif\utils\exceptions.py
class ONVIFOperationException(Exception):
"""Enhanced exception wrapper for ONVIF operation failures.
This exception provides detailed error information including operation name,
error category, SOAP fault details, and the original exception.
It categorizes errors into three types: **SOAP**, **Protocol**, and **Application** errors.
Attributes:
operation (str): Name of the ONVIF operation that failed
original_exception (Exception): The underlying exception that was raised
!!! tip "Version History"
- Available since [`>=v0.0.1`](/onvif-python/releases/#v0.0.1) (first release).
## Error Categories
### SOAP Error
Device returned a SOAP fault (e.g., `ActionNotSupported`):
- Includes fault code, subcode, message, and detail
- Supports both SOAP 1.1 and 1.2 formats
- Extracts readable information from XML fault details
!!! bug "Common SOAP Fault Subcodes"
- `ActionNotSupported`: Operation not implemented by device
- `NotAuthorized`: Authentication failed or insufficient permissions
- `InvalidArgVal`: Invalid parameter value
- `OperationProhibited`: Operation not allowed in current state
- `Sender`: Client-side error in request
- `Receiver`: Server-side error in device
### Protocol Error
Network/HTTP transport failed:
- Connection errors, timeouts, SSL errors
- HTTP status errors (404, 401, 500, etc.)
- DNS resolution failures
### Application Error
Generic/unexpected errors:
- Python exceptions, type errors, etc.
- Fallback category for uncategorized errors
??? example "Example Error Messages"
**SOAP Error** - Action Not Supported
```python
ONVIF operation 'GetImagingSettings' failed: SOAP Error: code=Receiver, subcode=ActionNotSupported, msg=Optional Action Not Implemented
```
**SOAP Error** - Invalid Argument
```python
ONVIF operation 'SetVideoEncoderConfiguration' failed: SOAP Error: code=Sender, subcode=InvalidArgVal, msg=Invalid resolution, detail=Width=1920, Height=1080
```
**Protocol Error** - Connection Timeout
```python
ONVIF operation 'GetCapabilities' failed: Protocol Error: HTTPConnectionPool(host='192.168.1.100', port=80): Read timed out.
```
**Application Error** - Missing Argument
```python
ONVIF operation 'UpgradeSystemFirmware' failed: Application Error: TypeError - Device.UpgradeSystemFirmware() missing 1 required positional argument: 'Firmware'
```
??? note "Notes"
- Always wraps the original exception for full error context
- Preserves stack trace through exception chaining
- Extracts maximum information from SOAP fault details
- Handles both `lxml.etree.QName` objects and strings in subcodes
- Safe handling of missing or malformed fault information
- Compatible with Python exception handling best practices
??? note "See Also"
- [`Error Handlers`](onvif_error_handlers.md): Utilities for handling specific error types
- `zeep.exceptions.Fault`: Base SOAP fault exception
- `requests.exceptions.RequestException`: Base HTTP error
"""
def __init__(self, operation, original_exception):
self.operation = operation
self.original_exception = original_exception
if isinstance(original_exception, Fault):
# SOAP-level error
category = "SOAP Error"
# Extract fault information (supports both SOAP 1.1 and 1.2)
code = getattr(original_exception, "code", None) or getattr(
original_exception, "faultcode", None
)
subcodes = getattr(original_exception, "subcodes", None)
message = getattr(original_exception, "message", None) or str(
original_exception
)
detail = getattr(original_exception, "detail", None)
# Convert subcodes from QName objects to readable strings
if subcodes is not None:
try:
# subcodes is a list of lxml.etree.QName objects
# QName objects have .localname (e.g., "ActionNotSupported")
# and .namespace (e.g., "http://www.onvif.org/ver10/error")
subcode_strings = []
for qname in subcodes:
if hasattr(qname, "localname"):
# Use only the local name without namespace
subcode_strings.append(qname.localname)
else:
# Fallback to string representation
subcode_strings.append(str(qname))
subcodes = ", ".join(subcode_strings)
except (AttributeError, TypeError, ValueError):
subcodes = str(subcodes)
# Build comprehensive error message
parts = []
if code:
parts.append(f"code={code}")
if subcodes:
parts.append(f"subcode={subcodes}")
if message and message.strip(): # Only add if message has content
parts.append(f"msg={message}")
if detail is not None:
# Parse XML detail element to extract readable content
try:
if hasattr(detail, "text") and detail.text:
detail_text = detail.text.strip()
elif hasattr(detail, "__iter__"):
# Try to extract text from child elements
detail_parts = []
for child in detail:
if hasattr(child, "text") and child.text:
detail_parts.append(
f"{child.tag.split('}')[-1]}={child.text}"
)
elif hasattr(child, "tag"):
detail_parts.append(child.tag.split("}")[-1])
detail_text = (
", ".join(detail_parts) if detail_parts else str(detail)
)
else:
detail_text = str(detail)
parts.append(f"detail={detail_text}")
except (AttributeError, TypeError, ValueError):
# Fallback to string representation
parts.append(f"detail={detail!s}")
msg = f"{category}: {', '.join(parts)}"
elif isinstance(original_exception, requests.exceptions.RequestException):
# Transport/Protocol error
category = "Protocol Error"
msg = f"{category}: {original_exception!s}"
else:
# Application or generic error
category = "Application Error"
# For better error messages, include exception type
exception_type = type(original_exception).__name__
exception_msg = str(original_exception)
# For some exceptions like KeyError, TypeError, add more context
if isinstance(original_exception, KeyError):
msg = f"{category}: KeyError - Missing key {exception_msg}"
elif isinstance(original_exception, TypeError):
msg = f"{category}: TypeError - {exception_msg}"
elif isinstance(original_exception, ValueError):
msg = f"{category}: ValueError - {exception_msg}"
elif isinstance(original_exception, AttributeError):
msg = f"{category}: AttributeError - {exception_msg}"
else:
# Generic format with exception type
msg = f"{category}: {exception_type} - {exception_msg}"
super().__init__(f"ONVIF operation '{operation}' failed: {msg}")