0
# Exception Handling
1
2
The TD Ameritrade Python API provides custom exception classes for handling different types of API errors and HTTP response codes. These exceptions help identify specific error conditions and enable appropriate error handling strategies.
3
4
## Core Import
5
6
```python
7
from td.exceptions import (
8
TknExpError, ExdLmtError, NotNulError,
9
ForbidError, NotFndError, ServerError, GeneralError
10
)
11
```
12
13
## Capabilities
14
15
### Token Expiration Errors
16
17
Exception raised when access tokens have expired and need to be refreshed.
18
19
```python { .api }
20
class TknExpError(Exception):
21
def __init__(self, message: str) -> None: ...
22
```
23
24
**Usage:** Raised when API calls fail due to expired access tokens. Indicates that token refresh is required before retrying the request.
25
26
### API Limit Exceeded Errors
27
28
Exception raised when API query limits or rate limits have been exceeded.
29
30
```python { .api }
31
class ExdLmtError(Exception):
32
def __init__(self, message: str) -> None: ...
33
```
34
35
**Usage:** Raised when the API returns rate limiting errors. Indicates that request frequency should be reduced or retry delays should be implemented.
36
37
### Null Value Errors
38
39
Exception raised when null values are provided for required fields.
40
41
```python { .api }
42
class NotNulError(Exception):
43
def __init__(self, message: str) -> None: ...
44
```
45
46
**Usage:** Raised when API requests contain null or missing values for required parameters. Indicates that required fields need to be provided.
47
48
### Forbidden Access Errors
49
50
Exception raised for HTTP 403 Forbidden responses indicating insufficient permissions.
51
52
```python { .api }
53
class ForbidError(Exception):
54
def __init__(self, message: str) -> None: ...
55
```
56
57
**Usage:** Raised when API calls are rejected due to insufficient permissions or unauthorized access. May indicate account permission restrictions or invalid authentication.
58
59
### Resource Not Found Errors
60
61
Exception raised when requested resources or criteria are not found.
62
63
```python { .api }
64
class NotFndError(Exception):
65
def __init__(self, message: str) -> None: ...
66
```
67
68
**Usage:** Raised when API requests reference resources that don't exist, such as invalid account numbers, order IDs, or symbol names.
69
70
### Server-side Errors
71
72
Exception raised for HTTP 500+ server errors indicating TD Ameritrade service issues.
73
74
```python { .api }
75
class ServerError(Exception):
76
def __init__(self, message: str) -> None: ...
77
```
78
79
**Usage:** Raised when TD Ameritrade API servers return internal server errors. Indicates temporary service issues that may resolve with retry attempts.
80
81
### General HTTP Errors
82
83
Exception raised for general HTTP 400+ status codes not covered by specific exceptions.
84
85
```python { .api }
86
class GeneralError(Exception):
87
def __init__(self, message: str) -> None: ...
88
```
89
90
**Usage:** Raised for HTTP error responses that don't fall into other specific error categories. Provides general error handling for various API response codes.
91
92
## Usage Examples
93
94
### Basic Exception Handling
95
96
```python
97
from td.client import TDClient
98
from td.exceptions import TknExpError, ForbidError, NotFndError
99
100
try:
101
client = TDClient(
102
client_id='your_client_id@AMER.OAUTHAP',
103
redirect_uri='http://localhost:8080/callback'
104
)
105
client.login()
106
107
# Get quotes
108
quotes = client.get_quotes(['AAPL', 'MSFT'])
109
print(quotes)
110
111
except TknExpError as e:
112
print(f"Token expired: {e}")
113
# Handle token refresh
114
client.grab_access_token()
115
116
except ForbidError as e:
117
print(f"Access forbidden: {e}")
118
# Check account permissions or re-authenticate
119
120
except NotFndError as e:
121
print(f"Resource not found: {e}")
122
# Verify symbols or resource identifiers
123
```
124
125
### Comprehensive Error Handling
126
127
```python
128
from td.exceptions import *
129
130
def safe_api_call(client, operation, *args, **kwargs):
131
"""Wrapper function with comprehensive error handling"""
132
try:
133
return operation(*args, **kwargs)
134
135
except TknExpError:
136
print("Token expired, refreshing...")
137
client.grab_access_token()
138
# Retry the operation
139
return operation(*args, **kwargs)
140
141
except ExdLmtError:
142
print("Rate limit exceeded, waiting...")
143
import time
144
time.sleep(60) # Wait 1 minute
145
return operation(*args, **kwargs)
146
147
except ForbidError as e:
148
print(f"Access forbidden: {e}")
149
print("Check account permissions or authentication")
150
return None
151
152
except NotFndError as e:
153
print(f"Resource not found: {e}")
154
print("Verify the requested resource exists")
155
return None
156
157
except NotNulError as e:
158
print(f"Required field missing: {e}")
159
print("Provide all required parameters")
160
return None
161
162
except ServerError as e:
163
print(f"Server error: {e}")
164
print("TD Ameritrade service issue, try again later")
165
return None
166
167
except GeneralError as e:
168
print(f"API error: {e}")
169
print("General API error occurred")
170
return None
171
172
# Usage
173
client = TDClient(client_id='...', redirect_uri='...')
174
client.login()
175
176
# Safe API calls
177
quotes = safe_api_call(client, client.get_quotes, ['AAPL', 'MSFT'])
178
accounts = safe_api_call(client, client.get_accounts)
179
```
180
181
### Retry Logic with Exceptions
182
183
```python
184
import time
185
from td.exceptions import TknExpError, ExdLmtError, ServerError
186
187
def retry_api_call(client, operation, max_retries=3, *args, **kwargs):
188
"""Retry API calls with exponential backoff"""
189
for attempt in range(max_retries):
190
try:
191
return operation(*args, **kwargs)
192
193
except TknExpError:
194
print(f"Attempt {attempt + 1}: Token expired, refreshing...")
195
client.grab_access_token()
196
197
except ExdLmtError:
198
wait_time = (2 ** attempt) * 60 # Exponential backoff
199
print(f"Attempt {attempt + 1}: Rate limited, waiting {wait_time}s...")
200
time.sleep(wait_time)
201
202
except ServerError:
203
wait_time = (2 ** attempt) * 30
204
print(f"Attempt {attempt + 1}: Server error, waiting {wait_time}s...")
205
time.sleep(wait_time)
206
207
if attempt == max_retries - 1:
208
print("Max retries exceeded")
209
raise
210
211
return None
212
213
# Usage with retry logic
214
try:
215
quotes = retry_api_call(client, client.get_quotes, 3, ['AAPL', 'MSFT'])
216
print(quotes)
217
except Exception as e:
218
print(f"Failed after retries: {e}")
219
```
220
221
### Order Placement Error Handling
222
223
```python
224
from td.orders import Order, OrderLeg
225
from td.exceptions import NotNulError, ForbidError, GeneralError
226
227
def place_order_safely(client, account_id, order):
228
"""Safely place an order with proper error handling"""
229
try:
230
response = client.place_order(account_id, order)
231
print(f"Order placed successfully: {response}")
232
return response
233
234
except NotNulError as e:
235
print(f"Missing required order fields: {e}")
236
print("Check that all order legs have required parameters")
237
return None
238
239
except ForbidError as e:
240
print(f"Order rejected - insufficient permissions: {e}")
241
print("Check account trading permissions")
242
return None
243
244
except GeneralError as e:
245
print(f"Order rejected: {e}")
246
print("Check order parameters and market conditions")
247
return None
248
249
# Create and place order with error handling
250
order = Order()
251
order.order_type('LIMIT')
252
order.order_price(150.00)
253
254
leg = OrderLeg()
255
leg.order_leg_instruction('BUY')
256
leg.order_leg_asset('EQUITY', 'AAPL')
257
leg.order_leg_quantity(100)
258
259
order.add_order_leg(leg)
260
261
result = place_order_safely(client, '123456789', order)
262
```
263
264
### Streaming Error Handling
265
266
```python
267
from td.stream import TDStreamerClient
268
from td.exceptions import TknExpError, ServerError
269
270
def start_streaming_safely(client):
271
"""Start streaming with error handling"""
272
try:
273
streaming_client = client.create_streaming_session()
274
streaming_client.level_one_quotes(['AAPL', 'MSFT'])
275
streaming_client.stream()
276
277
except TknExpError:
278
print("Streaming authentication failed, refreshing tokens...")
279
client.grab_access_token()
280
# Recreate streaming session
281
streaming_client = client.create_streaming_session()
282
streaming_client.level_one_quotes(['AAPL', 'MSFT'])
283
streaming_client.stream()
284
285
except ServerError as e:
286
print(f"Streaming server error: {e}")
287
print("TD Ameritrade streaming service issue")
288
289
except Exception as e:
290
print(f"Streaming error: {e}")
291
print("General streaming error occurred")
292
293
# Start streaming with error handling
294
start_streaming_safely(client)
295
```
296
297
### Context Manager for Error Handling
298
299
```python
300
from contextlib import contextmanager
301
from td.exceptions import TknExpError
302
303
@contextmanager
304
def td_api_session(client):
305
"""Context manager for TD API sessions with automatic token refresh"""
306
try:
307
yield client
308
except TknExpError:
309
print("Token expired during session, refreshing...")
310
client.grab_access_token()
311
yield client
312
313
# Usage with context manager
314
client = TDClient(client_id='...', redirect_uri='...')
315
client.login()
316
317
with td_api_session(client) as session:
318
quotes = session.get_quotes(['AAPL'])
319
accounts = session.get_accounts()
320
orders = session.get_orders('123456789')
321
```
322
323
## Error Response Codes
324
325
The exceptions map to specific HTTP response codes and TD Ameritrade API error conditions:
326
327
- **TknExpError**: Token expiration (401 Unauthorized)
328
- **ExdLmtError**: Rate limiting (429 Too Many Requests)
329
- **NotNulError**: Missing required fields (400 Bad Request)
330
- **ForbidError**: Insufficient permissions (403 Forbidden)
331
- **NotFndError**: Resource not found (404 Not Found)
332
- **ServerError**: Server issues (500+ Server Errors)
333
- **GeneralError**: Other HTTP errors (400+ Client/Server Errors)
334
335
## Best Practices
336
337
1. **Always handle TknExpError** - Tokens expire regularly and need refresh
338
2. **Implement retry logic** for ExdLmtError and ServerError conditions
339
3. **Validate inputs** before API calls to prevent NotNulError and NotFndError
340
4. **Check account permissions** when encountering ForbidError
341
5. **Use context managers** for automatic error handling in sessions
342
6. **Log errors appropriately** for debugging and monitoring
343
7. **Implement exponential backoff** for rate limiting scenarios