0
# Error Handling
1
2
Comprehensive error handling system for AWS CLI operations, providing structured exception handling, HTTP error processing, and user-friendly error reporting for both command-line and programmatic usage.
3
4
## Capabilities
5
6
### Core Exception Classes
7
8
Base exception classes for different categories of AWS CLI errors.
9
10
```python { .api }
11
class UnknownArgumentError(Exception):
12
"""
13
Raised when an unknown or invalid CLI argument is encountered.
14
Typically occurs during argument parsing.
15
"""
16
17
class ParamError(Exception):
18
"""
19
Base exception for parameter processing and validation errors.
20
Parent class for all parameter-related exceptions.
21
"""
22
23
class ParamSyntaxError(ParamError):
24
"""
25
Raised when parameter syntax is malformed or invalid.
26
Common with JSON parameter values or shorthand syntax.
27
"""
28
29
class ParamUnknownKeyError(ParamError):
30
"""
31
Raised when an unknown parameter key is encountered.
32
Occurs when using invalid keys in JSON or shorthand parameters.
33
"""
34
```
35
36
### HTTP Error Processing
37
38
Specialized error handling for AWS service HTTP responses.
39
40
```python { .api }
41
class ErrorHandler:
42
"""
43
HTTP error handler for AWS service responses.
44
Processes 4xx and 5xx HTTP errors into user-friendly messages.
45
"""
46
47
def __init__(self):
48
"""Initialize error handler."""
49
50
def __call__(self, parsed, **kwargs):
51
"""
52
Process HTTP error response.
53
54
Parameters:
55
parsed: botocore parsed response
56
**kwargs: additional context information
57
"""
58
59
class ClientError(Exception):
60
"""
61
Raised for HTTP 4xx client errors.
62
Indicates issues with the request (authentication, validation, etc.).
63
"""
64
65
def __init__(self, error_response, operation_name):
66
"""
67
Initialize client error.
68
69
Parameters:
70
error_response: dict, AWS error response
71
operation_name: str, AWS operation name
72
"""
73
74
class ServerError(Exception):
75
"""
76
Raised for HTTP 5xx server errors.
77
Indicates issues with AWS service availability or processing.
78
"""
79
80
class BaseOperationError(Exception):
81
"""
82
Base class for operation-level errors.
83
Parent class for service operation exceptions.
84
"""
85
```
86
87
### Error Utilities
88
89
Utility functions for error processing and display.
90
91
```python { .api }
92
def write_exception(ex, outfile):
93
"""
94
Write exception information to output file.
95
96
Parameters:
97
ex: Exception instance
98
outfile: file-like object for error output
99
"""
100
```
101
102
**Usage Example:**
103
```python
104
from awscli.utils import write_exception
105
import sys
106
107
try:
108
# AWS CLI operation that might fail
109
result = driver.main(['s3', 'ls', 's3://nonexistent-bucket'])
110
except Exception as e:
111
# Write error to stderr with proper formatting
112
write_exception(e, sys.stderr)
113
sys.exit(1)
114
```
115
116
## Error Handling Patterns
117
118
### Argument Processing Errors
119
120
Common patterns for handling argument-related errors:
121
122
```python
123
from awscli.arguments import UnknownArgumentError
124
from awscli.argprocess import ParamError, ParamSyntaxError
125
126
def process_arguments(args):
127
try:
128
# Process CLI arguments
129
processed_args = parse_arguments(args)
130
return processed_args
131
except UnknownArgumentError as e:
132
print(f"Unknown argument: {e}")
133
return None
134
except ParamSyntaxError as e:
135
print(f"Parameter syntax error: {e}")
136
return None
137
except ParamError as e:
138
print(f"Parameter error: {e}")
139
return None
140
```
141
142
### Service Operation Error Handling
143
144
Handling AWS service operation errors:
145
146
```python
147
from botocore.exceptions import ClientError, NoCredentialsError
148
from awscli.clidriver import main
149
150
def execute_aws_command(command_args):
151
try:
152
exit_code = main(command_args)
153
return exit_code == 0
154
except ClientError as e:
155
error_code = e.response['Error']['Code']
156
error_message = e.response['Error']['Message']
157
158
if error_code == 'NoSuchBucket':
159
print(f"Bucket does not exist: {error_message}")
160
elif error_code == 'AccessDenied':
161
print(f"Access denied: {error_message}")
162
else:
163
print(f"AWS error ({error_code}): {error_message}")
164
return False
165
except NoCredentialsError:
166
print("AWS credentials not configured")
167
return False
168
except Exception as e:
169
print(f"Unexpected error: {e}")
170
return False
171
```
172
173
### Custom Command Error Handling
174
175
Error handling in custom commands:
176
177
```python
178
from awscli.customizations.commands import BasicCommand
179
from awscli.arguments import ParamError
180
181
class MyCustomCommand(BasicCommand):
182
NAME = 'my-command'
183
184
def _run_main(self, parsed_args, parsed_globals):
185
try:
186
# Custom command logic
187
self.process_input(parsed_args.input_file)
188
return 0
189
except FileNotFoundError:
190
print(f"Input file not found: {parsed_args.input_file}")
191
return 1
192
except ParamError as e:
193
print(f"Parameter error: {e}")
194
return 1
195
except Exception as e:
196
print(f"Command failed: {e}")
197
return 1
198
199
def process_input(self, input_file):
200
"""Process input file with error handling."""
201
if not os.path.exists(input_file):
202
raise FileNotFoundError(f"File not found: {input_file}")
203
# Process file...
204
```
205
206
## Error Context and Debugging
207
208
### Error Context Preservation
209
210
AWS CLI preserves error context for debugging:
211
212
```python
213
def enhanced_error_handler(parsed, **kwargs):
214
"""Enhanced error handler with context preservation."""
215
if 'Error' in parsed:
216
error_info = parsed['Error']
217
218
# Preserve original error context
219
context = {
220
'operation': kwargs.get('operation_name'),
221
'service': kwargs.get('service'),
222
'request_id': parsed.get('ResponseMetadata', {}).get('RequestId'),
223
'http_status': parsed.get('ResponseMetadata', {}).get('HTTPStatusCode')
224
}
225
226
# Create enhanced error message
227
enhanced_message = format_error_with_context(error_info, context)
228
print(enhanced_message)
229
```
230
231
### Debug Mode Error Information
232
233
Enhanced error reporting in debug mode:
234
235
```python
236
import logging
237
238
# Enable debug logging for detailed error information
239
logging.basicConfig(level=logging.DEBUG)
240
241
# AWS CLI will provide additional error context:
242
# - HTTP request/response details
243
# - Parameter validation information
244
# - Service model validation
245
# - Plugin execution traces
246
```
247
248
### Common Error Categories
249
250
**Authentication Errors:**
251
- `NoCredentialsError`: AWS credentials not configured
252
- `UnauthorizedOperation`: Insufficient permissions
253
- `InvalidUserID.NotFound`: User/role not found
254
255
**Validation Errors:**
256
- `ValidationException`: Parameter validation failed
257
- `InvalidParameterValue`: Invalid parameter value
258
- `MissingParameter`: Required parameter missing
259
260
**Service Errors:**
261
- `ServiceUnavailable`: AWS service temporarily unavailable
262
- `Throttling`: Request rate exceeded
263
- `InternalError`: AWS internal processing error
264
265
**Network Errors:**
266
- `EndpointConnectionError`: Cannot connect to AWS endpoint
267
- `ConnectTimeout`: Connection timeout
268
- `ReadTimeout`: Read operation timeout
269
270
### Error Recovery Strategies
271
272
**Retry Logic:**
273
```python
274
import time
275
from botocore.exceptions import ClientError
276
277
def execute_with_retry(command_args, max_attempts=3):
278
for attempt in range(max_attempts):
279
try:
280
return main(command_args)
281
except ClientError as e:
282
if e.response['Error']['Code'] == 'Throttling':
283
if attempt < max_attempts - 1:
284
wait_time = 2 ** attempt # Exponential backoff
285
time.sleep(wait_time)
286
continue
287
raise
288
```
289
290
**Fallback Handling:**
291
```python
292
def execute_with_fallback(primary_command, fallback_command):
293
try:
294
return main(primary_command)
295
except ClientError as e:
296
if e.response['Error']['Code'] in ['ServiceUnavailable', 'InternalError']:
297
print("Primary service unavailable, trying fallback...")
298
return main(fallback_command)
299
raise
300
```