Error Handling
The Zscaler SDK provides a comprehensive exception hierarchy for handling errors.
The SDK normalizes error handling across all services (Authentication Service, Client Connector, Cloud & Branch Connector, ZDX, ZIA, and ZPA), so you work with the same exception classes irrespective of which service raised them. At the same time, it preserves service-specific error details on each exception instance, including HTTP status code, request ID, error message, and resource or action context.
For a full list of HTTP status codes that OneAPI returns and the service-specific error codes that each product might return, see Understanding Response Codes & Error Messages. You can also access individual product pages (Authentication Service, Business Insights, Client Connector, Cloud & Branch Connector, ZDX, ZIA, and ZPA) from there.
Exception Hierarchy
OneApiError (base)
├── ZsResourceError (resource layer)
│ ├── BadRequestException (400)
│ ├── AuthenticationException (401)
│ ├── AuthenticationException (403)
│ ├─ ─ NotFoundException (404)
│ ├── RequestTimeoutException (408)
│ ├── ConflictException (409)
│ ├── GoneException (410)
│ ├── PreconditionFailedException (412)
│ ├── PreconditionRequiredException (428)
│ ├── ThrottledException (429)
│ └── ParamValidationError (client-side validation)
Basic Error Handling
import zssdk
from zssdk.zscore.config import Config, LoggerConfig
from zssdk.zscore import OneApiError
from zssdk.zsresource import ZsResourceError
from zssdk.zsresource.exceptions import (
BadRequestException,
NotFoundException,
AuthenticationException,
ThrottledException,
)
# Enable debug logging for troubleshooting
logger_config = LoggerConfig(
enabled=True,
verbose=True,
log_to_file=True,
log_file_path="error_handling.log",
)
config = Config(logger_config=logger_config)
session = zssdk.Session(
vanity_domain="your-vanity-domain",
client_id="your-client-id",
client_secret="your-client-secret",
config=config
)
try:
role = session.zia.AdminRole(id=99999)
role.load()
except NotFoundException as e:
print(f"Role not found: {e}")
except BadRequestException as e:
print(f"Invalid request: {e}")
print(f"Status code: {e.status_code}")
except AuthenticationException as e:
print(f"Authentication failed: {e}")
except ThrottledException as e:
print(f"Rate limited (status {e.status_code}): {e}")
except ZsResourceError as e:
print(f"Resource error: {e}")
except OneApiError as e:
print(f"SDK error: {e}")
Exception Attributes
All exceptions include the following useful attributes:
try:
role = session.zia.AdminRole(id=99999)
role.load()
except ZsResourceError as e:
print(f"Error type: {type(e).__name__}")
print(f"Message: {e}")
print(f"Status code: {e.status_code}")
print(f"Resource: {e.resource_name}")
print(f"Action: {e.action_name}")
print(f"Request ID: {e.request_id}")
Common Error Scenarios
400 Bad Request
Invalid parameters or malformed request:
try:
role = session.zia.AdminRole()
role.name = "" # Empty name is invalid
role.create()
except BadRequestException as e:
print(f"Validation error: {e}")
# Debug logging shows the exact request that failed
401 or 403 Authentication Error
Invalid or expired credentials:
try:
session = zssdk.Session(
vanity_domain="your-vanity-domain",
client_id="invalid",
client_secret="invalid",
)
list(session.zia.admin_roles)
except AuthenticationException as e:
print(f"Check your credentials: {e}")
print(f"Status code: {e.status_code}")
404 Not Found
Resource doesn't exist:
try:
role = session.zia.AdminRole(id=99999)
role.load()
except NotFoundException as e:
print(f"Role ID 99999 not found")
print(f"Resource: {e.resource_name}")
409 Conflict
Resource already exists or is in a conflicting state:
try:
# Try to create duplicate resource
role = session.zia.AdminRole()
role.name = "Existing Role"
role.create()
except ConflictException as e:
print(f"Resource conflict: {e}")
print(f"Consider using update() instead of create()")
429 Rate Limit
Too many requests:
from zssdk.zsresource.exceptions import ThrottledException
try:
# The SDK transparently retries on 429 with exponential backoff
# before raising. By the time you catch ThrottledException here,
# automatic retries have already been exhausted — typically you
# want to back off in the application (slow the caller, push to a
# dead-letter queue, etc.) rather than retry again immediately.
for i in range(1000):
list(session.zia.admin_roles)
except ThrottledException as e:
print(f"Still rate limited after SDK retries: {e}")
print(f"Status code: {e.status_code}")
500+ Server Errors
Server-side issues:
from zssdk.zscore import OneApiError
try:
# Server-side failures (5xx) surface as the generic OneApiError —
# there is no dedicated ServerException class. The SDK's transport
# layer already retries transient 5xx responses (with exponential
# backoff, capped at 300 s, up to max_attempts) before raising,
# so by the time you catch this exception automatic retries are
# exhausted and you should fall back to application-level handling.
role = session.zia.AdminRole(id="your-role-id")
role.load()
except OneApiError as e:
print(f"Server error: {e}")
print(f"Status code: {e.status_code}")
Debugging with Logs
Enable comprehensive logging to troubleshoot errors:
import zssdk
from zssdk.zscore.config import Config, LoggerConfig
# Configure detailed logging using SDK's LoggerConfig
logger_config = LoggerConfig(
enabled=True,
verbose=True,
log_to_file=True,
log_file_path="debug_errors.log",
)
config = Config(logger_config=logger_config)
# Session with comprehensive logging enabled
session = zssdk.Session(
vanity_domain="your-vanity-domain",
client_id="your-client-id",
client_secret="your-client-secret",
config=config
)
# Debug output shows:
# - HTTP request details (URL, headers, body)
# - HTTP response details (status, headers, body)
# - Token refresh attempts
# - Resource processing steps
# - Error parsing and exception creation
Related
- Understanding Response Codes & Error Messages: Complete reference for HTTP status codes and service-specific error codes (Authentication Service, Business Insights, Client Connector, Cloud & Branch Connector, ZDX, ZIA, and ZPA)
- Rate Limiting guide: Explains how
ThrottledException(429) is handled and retried automatically - Logging guide: Shows how to enable verbose logging to inspect the exact request and response that triggered an exception