1# Copyright (c) 2012-2013 Mitch Garnaat http://garnaat.org/
2# Copyright 2012-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"). You
5# may not use this file except in compliance with the License. A copy of
6# the License is located at
7#
8# http://aws.amazon.com/apache2.0/
9#
10# or in the "license" file accompanying this file. This file is
11# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
12# ANY KIND, either express or implied. See the License for the specific
13# language governing permissions and limitations under the License.
14
15from botocore.vendored import requests
16from botocore.vendored.requests.packages import urllib3
17
18
19def _exception_from_packed_args(exception_cls, args=None, kwargs=None):
20 # This is helpful for reducing Exceptions that only accept kwargs as
21 # only positional arguments can be provided for __reduce__
22 # Ideally, this would also be a class method on the BotoCoreError
23 # but instance methods cannot be pickled.
24 if args is None:
25 args = ()
26 if kwargs is None:
27 kwargs = {}
28 return exception_cls(*args, **kwargs)
29
30
31class BotoCoreError(Exception):
32 """
33 The base exception class for BotoCore exceptions.
34
35 :ivar msg: The descriptive message associated with the error.
36 """
37
38 fmt = 'An unspecified error occurred'
39
40 def __init__(self, **kwargs):
41 msg = self.fmt.format(**kwargs)
42 Exception.__init__(self, msg)
43 self.kwargs = kwargs
44
45 def __reduce__(self):
46 return _exception_from_packed_args, (self.__class__, None, self.kwargs)
47
48
49class DataNotFoundError(BotoCoreError):
50 """
51 The data associated with a particular path could not be loaded.
52
53 :ivar data_path: The data path that the user attempted to load.
54 """
55
56 fmt = 'Unable to load data for: {data_path}'
57
58
59class UnknownServiceError(DataNotFoundError):
60 """Raised when trying to load data for an unknown service.
61
62 :ivar service_name: The name of the unknown service.
63
64 """
65
66 fmt = (
67 "Unknown service: '{service_name}'. Valid service names are: "
68 "{known_service_names}"
69 )
70
71
72class UnknownRegionError(BotoCoreError):
73 """Raised when trying to load data for an unknown region.
74
75 :ivar region_name: The name of the unknown region.
76
77 """
78
79 fmt = "Unknown region: '{region_name}'. {error_msg}"
80
81
82class ApiVersionNotFoundError(BotoCoreError):
83 """
84 The data associated with either the API version or a compatible one
85 could not be loaded.
86
87 :ivar data_path: The data path that the user attempted to load.
88 :ivar api_version: The API version that the user attempted to load.
89 """
90
91 fmt = 'Unable to load data {data_path} for: {api_version}'
92
93
94class HTTPClientError(BotoCoreError):
95 fmt = 'An HTTP Client raised an unhandled exception: {error}'
96
97 def __init__(self, request=None, response=None, **kwargs):
98 self.request = request
99 self.response = response
100 super().__init__(**kwargs)
101
102 def __reduce__(self):
103 return _exception_from_packed_args, (
104 self.__class__,
105 (self.request, self.response),
106 self.kwargs,
107 )
108
109
110class ConnectionError(BotoCoreError):
111 fmt = 'An HTTP Client failed to establish a connection: {error}'
112
113
114class InvalidIMDSEndpointError(BotoCoreError):
115 fmt = 'Invalid endpoint EC2 Instance Metadata endpoint: {endpoint}'
116
117
118class InvalidIMDSEndpointModeError(BotoCoreError):
119 fmt = (
120 'Invalid EC2 Instance Metadata endpoint mode: {mode}'
121 ' Valid endpoint modes (case-insensitive): {valid_modes}.'
122 )
123
124
125class EndpointConnectionError(ConnectionError):
126 fmt = 'Could not connect to the endpoint URL: "{endpoint_url}"'
127
128
129class SSLError(ConnectionError, requests.exceptions.SSLError):
130 fmt = 'SSL validation failed for {endpoint_url} {error}'
131
132
133class ConnectionClosedError(HTTPClientError):
134 fmt = (
135 'Connection was closed before we received a valid response '
136 'from endpoint URL: "{endpoint_url}".'
137 )
138
139
140class ReadTimeoutError(
141 HTTPClientError,
142 requests.exceptions.ReadTimeout,
143 urllib3.exceptions.ReadTimeoutError,
144):
145 fmt = 'Read timeout on endpoint URL: "{endpoint_url}"'
146
147
148class ConnectTimeoutError(ConnectionError, requests.exceptions.ConnectTimeout):
149 fmt = 'Connect timeout on endpoint URL: "{endpoint_url}"'
150
151
152class ProxyConnectionError(ConnectionError, requests.exceptions.ProxyError):
153 fmt = 'Failed to connect to proxy URL: "{proxy_url}"'
154
155
156class ResponseStreamingError(HTTPClientError):
157 fmt = 'An error occurred while reading from response stream: {error}'
158
159
160class NoCredentialsError(BotoCoreError):
161 """
162 No credentials could be found.
163 """
164
165 fmt = 'Unable to locate credentials'
166
167
168class NoAuthTokenError(BotoCoreError):
169 """
170 No authorization token could be found.
171 """
172
173 fmt = 'Unable to locate authorization token'
174
175
176class TokenRetrievalError(BotoCoreError):
177 """
178 Error attempting to retrieve a token from a remote source.
179
180 :ivar provider: The name of the token provider.
181 :ivar error_msg: The msg explaining why the token could not be retrieved.
182
183 """
184
185 fmt = 'Error when retrieving token from {provider}: {error_msg}'
186
187
188class PartialCredentialsError(BotoCoreError):
189 """
190 Only partial credentials were found.
191
192 :ivar cred_var: The missing credential variable name.
193
194 """
195
196 fmt = 'Partial credentials found in {provider}, missing: {cred_var}'
197
198
199class CredentialRetrievalError(BotoCoreError):
200 """
201 Error attempting to retrieve credentials from a remote source.
202
203 :ivar provider: The name of the credential provider.
204 :ivar error_msg: The msg explaining why credentials could not be
205 retrieved.
206
207 """
208
209 fmt = 'Error when retrieving credentials from {provider}: {error_msg}'
210
211
212class UnknownSignatureVersionError(BotoCoreError):
213 """
214 Requested Signature Version is not known.
215
216 :ivar signature_version: The name of the requested signature version.
217 """
218
219 fmt = 'Unknown Signature Version: {signature_version}.'
220
221
222class ServiceNotInRegionError(BotoCoreError):
223 """
224 The service is not available in requested region.
225
226 :ivar service_name: The name of the service.
227 :ivar region_name: The name of the region.
228 """
229
230 fmt = 'Service {service_name} not available in region {region_name}'
231
232
233class BaseEndpointResolverError(BotoCoreError):
234 """Base error for endpoint resolving errors.
235
236 Should never be raised directly, but clients can catch
237 this exception if they want to generically handle any errors
238 during the endpoint resolution process.
239
240 """
241
242
243class NoRegionError(BaseEndpointResolverError):
244 """No region was specified."""
245
246 fmt = 'You must specify a region.'
247
248
249class EndpointVariantError(BaseEndpointResolverError):
250 """
251 Could not construct modeled endpoint variant.
252
253 :ivar error_msg: The message explaining why the modeled endpoint variant
254 is unable to be constructed.
255
256 """
257
258 fmt = (
259 'Unable to construct a modeled endpoint with the following '
260 'variant(s) {tags}: '
261 )
262
263
264class UnknownEndpointError(BaseEndpointResolverError, ValueError):
265 """
266 Could not construct an endpoint.
267
268 :ivar service_name: The name of the service.
269 :ivar region_name: The name of the region.
270 """
271
272 fmt = (
273 'Unable to construct an endpoint for '
274 '{service_name} in region {region_name}'
275 )
276
277
278class UnknownFIPSEndpointError(BaseEndpointResolverError):
279 """
280 Could not construct a FIPS endpoint.
281
282 :ivar service_name: The name of the service.
283 :ivar region_name: The name of the region.
284 """
285
286 fmt = (
287 'The provided FIPS pseudo-region "{region_name}" is not known for '
288 'the service "{service_name}". A FIPS compliant endpoint cannot be '
289 'constructed.'
290 )
291
292
293class ProfileNotFound(BotoCoreError):
294 """
295 The specified configuration profile was not found in the
296 configuration file.
297
298 :ivar profile: The name of the profile the user attempted to load.
299 """
300
301 fmt = 'The config profile ({profile}) could not be found'
302
303
304class ConfigParseError(BotoCoreError):
305 """
306 The configuration file could not be parsed.
307
308 :ivar path: The path to the configuration file.
309 """
310
311 fmt = 'Unable to parse config file: {path}'
312
313
314class ConfigNotFound(BotoCoreError):
315 """
316 The specified configuration file could not be found.
317
318 :ivar path: The path to the configuration file.
319 """
320
321 fmt = 'The specified config file ({path}) could not be found.'
322
323
324class MissingParametersError(BotoCoreError):
325 """
326 One or more required parameters were not supplied.
327
328 :ivar object: The object that has missing parameters.
329 This can be an operation or a parameter (in the
330 case of inner params). The str() of this object
331 will be used so it doesn't need to implement anything
332 other than str().
333 :ivar missing: The names of the missing parameters.
334 """
335
336 fmt = (
337 'The following required parameters are missing for '
338 '{object_name}: {missing}'
339 )
340
341
342class ValidationError(BotoCoreError):
343 """
344 An exception occurred validating parameters.
345
346 Subclasses must accept a ``value`` and ``param``
347 argument in their ``__init__``.
348
349 :ivar value: The value that was being validated.
350 :ivar param: The parameter that failed validation.
351 :ivar type_name: The name of the underlying type.
352 """
353
354 fmt = "Invalid value ('{value}') for param {param} of type {type_name} "
355
356
357class ParamValidationError(BotoCoreError):
358 fmt = 'Parameter validation failed:\n{report}'
359
360
361# These exceptions subclass from ValidationError so that code
362# can just 'except ValidationError' to catch any possibly validation
363# error.
364class UnknownKeyError(ValidationError):
365 """
366 Unknown key in a struct parameter.
367
368 :ivar value: The value that was being checked.
369 :ivar param: The name of the parameter.
370 :ivar choices: The valid choices the value can be.
371 """
372
373 fmt = (
374 "Unknown key '{value}' for param '{param}'. Must be one of: {choices}"
375 )
376
377
378class RangeError(ValidationError):
379 """
380 A parameter value was out of the valid range.
381
382 :ivar value: The value that was being checked.
383 :ivar param: The parameter that failed validation.
384 :ivar min_value: The specified minimum value.
385 :ivar max_value: The specified maximum value.
386 """
387
388 fmt = (
389 'Value out of range for param {param}: '
390 '{min_value} <= {value} <= {max_value}'
391 )
392
393
394class UnknownParameterError(ValidationError):
395 """
396 Unknown top level parameter.
397
398 :ivar name: The name of the unknown parameter.
399 :ivar operation: The name of the operation.
400 :ivar choices: The valid choices the parameter name can be.
401 """
402
403 fmt = (
404 "Unknown parameter '{name}' for operation {operation}. Must be one "
405 "of: {choices}"
406 )
407
408
409class InvalidRegionError(ValidationError, ValueError):
410 """
411 Invalid region_name provided to client or resource.
412
413 :ivar region_name: region_name that was being validated.
414 """
415
416 fmt = "Provided region_name '{region_name}' doesn't match a supported format."
417
418
419class AliasConflictParameterError(ValidationError):
420 """
421 Error when an alias is provided for a parameter as well as the original.
422
423 :ivar original: The name of the original parameter.
424 :ivar alias: The name of the alias
425 :ivar operation: The name of the operation.
426 """
427
428 fmt = (
429 "Parameter '{original}' and its alias '{alias}' were provided "
430 "for operation {operation}. Only one of them may be used."
431 )
432
433
434class UnknownServiceStyle(BotoCoreError):
435 """
436 Unknown style of service invocation.
437
438 :ivar service_style: The style requested.
439 """
440
441 fmt = 'The service style ({service_style}) is not understood.'
442
443
444class PaginationError(BotoCoreError):
445 fmt = 'Error during pagination: {message}'
446
447
448class OperationNotPageableError(BotoCoreError):
449 fmt = 'Operation cannot be paginated: {operation_name}'
450
451
452class ChecksumError(BotoCoreError):
453 """The expected checksum did not match the calculated checksum."""
454
455 fmt = (
456 'Checksum {checksum_type} failed, expected checksum '
457 '{expected_checksum} did not match calculated checksum '
458 '{actual_checksum}.'
459 )
460
461
462class UnseekableStreamError(BotoCoreError):
463 """Need to seek a stream, but stream does not support seeking."""
464
465 fmt = (
466 'Need to rewind the stream {stream_object}, but stream '
467 'is not seekable.'
468 )
469
470
471class WaiterError(BotoCoreError):
472 """Waiter failed to reach desired state."""
473
474 fmt = 'Waiter {name} failed: {reason}'
475
476 def __init__(self, name, reason, last_response):
477 super().__init__(name=name, reason=reason)
478 self.last_response = last_response
479
480
481class IncompleteReadError(BotoCoreError):
482 """HTTP response did not return expected number of bytes."""
483
484 fmt = '{actual_bytes} read, but total bytes expected is {expected_bytes}.'
485
486
487class InvalidExpressionError(BotoCoreError):
488 """Expression is either invalid or too complex."""
489
490 fmt = 'Invalid expression {expression}: Only dotted lookups are supported.'
491
492
493class UnknownCredentialError(BotoCoreError):
494 """Tried to insert before/after an unregistered credential type."""
495
496 fmt = 'Credential named {name} not found.'
497
498
499class WaiterConfigError(BotoCoreError):
500 """Error when processing waiter configuration."""
501
502 fmt = 'Error processing waiter config: {error_msg}'
503
504
505class UnknownClientMethodError(BotoCoreError):
506 """Error when trying to access a method on a client that does not exist."""
507
508 fmt = 'Client does not have method: {method_name}'
509
510
511class UnsupportedSignatureVersionError(BotoCoreError):
512 """Error when trying to use an unsupported Signature Version."""
513
514 fmt = 'Signature version(s) are not supported: {signature_version}'
515
516
517class ClientError(Exception):
518 MSG_TEMPLATE = (
519 'An error occurred ({error_code}) when calling the {operation_name} '
520 'operation{retry_info}: {error_message}'
521 )
522
523 def __init__(self, error_response, operation_name):
524 retry_info = self._get_retry_info(error_response)
525 error = error_response.get('Error', {})
526 msg = self.MSG_TEMPLATE.format(
527 error_code=error.get('Code', 'Unknown'),
528 error_message=error.get('Message', 'Unknown'),
529 operation_name=operation_name,
530 retry_info=retry_info,
531 )
532 super().__init__(msg)
533 self.response = error_response
534 self.operation_name = operation_name
535
536 def _get_retry_info(self, response):
537 retry_info = ''
538 if 'ResponseMetadata' in response:
539 metadata = response['ResponseMetadata']
540 if metadata.get('MaxAttemptsReached', False):
541 if 'RetryAttempts' in metadata:
542 retry_info = (
543 f" (reached max retries: {metadata['RetryAttempts']})"
544 )
545 return retry_info
546
547 def __reduce__(self):
548 # Subclasses of ClientError's are dynamically generated and
549 # cannot be pickled unless they are attributes of a
550 # module. So at the very least return a ClientError back.
551 return ClientError, (self.response, self.operation_name)
552
553
554class EventStreamError(ClientError):
555 pass
556
557
558class UnsupportedTLSVersionWarning(Warning):
559 """Warn when an openssl version that uses TLS 1.2 is required"""
560
561 pass
562
563
564class ImminentRemovalWarning(Warning):
565 pass
566
567
568class InvalidDNSNameError(BotoCoreError):
569 """Error when virtual host path is forced on a non-DNS compatible bucket"""
570
571 fmt = (
572 'Bucket named {bucket_name} is not DNS compatible. Virtual '
573 'hosted-style addressing cannot be used. The addressing style '
574 'can be configured by removing the addressing_style value '
575 'or setting that value to \'path\' or \'auto\' in the AWS Config '
576 'file or in the botocore.client.Config object.'
577 )
578
579
580class InvalidS3AddressingStyleError(BotoCoreError):
581 """Error when an invalid path style is specified"""
582
583 fmt = (
584 'S3 addressing style {s3_addressing_style} is invalid. Valid options '
585 'are: \'auto\', \'virtual\', and \'path\''
586 )
587
588
589class UnsupportedS3ArnError(BotoCoreError):
590 """Error when S3 ARN provided to Bucket parameter is not supported"""
591
592 fmt = (
593 'S3 ARN {arn} provided to "Bucket" parameter is invalid. Only '
594 'ARNs for S3 access-points are supported.'
595 )
596
597
598class UnsupportedS3ControlArnError(BotoCoreError):
599 """Error when S3 ARN provided to S3 control parameter is not supported"""
600
601 fmt = 'S3 ARN "{arn}" provided is invalid for this operation. {msg}'
602
603
604class InvalidHostLabelError(BotoCoreError):
605 """Error when an invalid host label would be bound to an endpoint"""
606
607 fmt = (
608 'Invalid host label to be bound to the hostname of the endpoint: '
609 '"{label}".'
610 )
611
612
613class UnsupportedOutpostResourceError(BotoCoreError):
614 """Error when S3 Outpost ARN provided to Bucket parameter is incomplete"""
615
616 fmt = (
617 'S3 Outpost ARN resource "{resource_name}" provided to "Bucket" '
618 'parameter is invalid. Only ARNs for S3 Outpost arns with an '
619 'access-point sub-resource are supported.'
620 )
621
622
623class UnsupportedS3ConfigurationError(BotoCoreError):
624 """Error when an unsupported configuration is used with access-points"""
625
626 fmt = 'Unsupported configuration when using S3: {msg}'
627
628
629class UnsupportedS3AccesspointConfigurationError(BotoCoreError):
630 """Error when an unsupported configuration is used with access-points"""
631
632 fmt = 'Unsupported configuration when using S3 access-points: {msg}'
633
634
635class InvalidEndpointDiscoveryConfigurationError(BotoCoreError):
636 """Error when invalid value supplied for endpoint_discovery_enabled"""
637
638 fmt = (
639 'Unsupported configuration value for endpoint_discovery_enabled. '
640 'Expected one of ("true", "false", "auto") but got {config_value}.'
641 )
642
643
644class UnsupportedS3ControlConfigurationError(BotoCoreError):
645 """Error when an unsupported configuration is used with S3 Control"""
646
647 fmt = 'Unsupported configuration when using S3 Control: {msg}'
648
649
650class InvalidRetryConfigurationError(BotoCoreError):
651 """Error when invalid retry configuration is specified"""
652
653 fmt = (
654 'Cannot provide retry configuration for "{retry_config_option}". '
655 'Valid retry configuration options are: {valid_options}'
656 )
657
658
659class InvalidMaxRetryAttemptsError(InvalidRetryConfigurationError):
660 """Error when invalid retry configuration is specified"""
661
662 fmt = (
663 'Value provided to "max_attempts": {provided_max_attempts} must '
664 'be an integer greater than or equal to {min_value}.'
665 )
666
667
668class InvalidRetryModeError(InvalidRetryConfigurationError):
669 """Error when invalid retry mode configuration is specified"""
670
671 fmt = (
672 'Invalid value provided to "mode": "{provided_retry_mode}" must '
673 'be one of: {valid_modes}'
674 )
675
676
677class InvalidS3UsEast1RegionalEndpointConfigError(BotoCoreError):
678 """Error for invalid s3 us-east-1 regional endpoints configuration"""
679
680 fmt = (
681 'S3 us-east-1 regional endpoint option '
682 '{s3_us_east_1_regional_endpoint_config} is '
683 'invalid. Valid options are: "legacy", "regional"'
684 )
685
686
687class InvalidSTSRegionalEndpointsConfigError(BotoCoreError):
688 """Error when invalid sts regional endpoints configuration is specified"""
689
690 fmt = (
691 'STS regional endpoints option {sts_regional_endpoints_config} is '
692 'invalid. Valid options are: "legacy", "regional"'
693 )
694
695
696class StubResponseError(BotoCoreError):
697 fmt = (
698 'Error getting response stub for operation {operation_name}: {reason}'
699 )
700
701
702class StubAssertionError(StubResponseError, AssertionError):
703 pass
704
705
706class UnStubbedResponseError(StubResponseError):
707 pass
708
709
710class InvalidConfigError(BotoCoreError):
711 fmt = '{error_msg}'
712
713
714class InfiniteLoopConfigError(InvalidConfigError):
715 fmt = (
716 'Infinite loop in credential configuration detected. Attempting to '
717 'load from profile {source_profile} which has already been visited. '
718 'Visited profiles: {visited_profiles}'
719 )
720
721
722class RefreshWithMFAUnsupportedError(BotoCoreError):
723 fmt = 'Cannot refresh credentials: MFA token required.'
724
725
726class MD5UnavailableError(BotoCoreError):
727 fmt = "This system does not support MD5 generation."
728
729
730class MissingDependencyException(BotoCoreError):
731 fmt = "Missing Dependency: {msg}"
732
733
734class MetadataRetrievalError(BotoCoreError):
735 fmt = "Error retrieving metadata: {error_msg}"
736
737
738class UndefinedModelAttributeError(Exception):
739 pass
740
741
742class MissingServiceIdError(UndefinedModelAttributeError):
743 fmt = (
744 "The model being used for the service {service_name} is missing the "
745 "serviceId metadata property, which is required."
746 )
747
748 def __init__(self, **kwargs):
749 msg = self.fmt.format(**kwargs)
750 Exception.__init__(self, msg)
751 self.kwargs = kwargs
752
753
754class SSOError(BotoCoreError):
755 fmt = (
756 "An unspecified error happened when resolving AWS credentials or an "
757 "access token from SSO."
758 )
759
760
761class SSOTokenLoadError(SSOError):
762 fmt = "Error loading SSO Token: {error_msg}"
763
764
765class UnauthorizedSSOTokenError(SSOError):
766 fmt = (
767 "The SSO session associated with this profile has expired or is "
768 "otherwise invalid. To refresh this SSO session run aws sso login "
769 "with the corresponding profile."
770 )
771
772
773class CapacityNotAvailableError(BotoCoreError):
774 fmt = 'Insufficient request capacity available.'
775
776
777class InvalidProxiesConfigError(BotoCoreError):
778 fmt = 'Invalid configuration value(s) provided for proxies_config.'
779
780
781class InvalidDefaultsMode(BotoCoreError):
782 fmt = (
783 'Client configured with invalid defaults mode: {mode}. '
784 'Valid defaults modes include: {valid_modes}.'
785 )
786
787
788class AwsChunkedWrapperError(BotoCoreError):
789 fmt = '{error_msg}'
790
791
792class FlexibleChecksumError(BotoCoreError):
793 fmt = '{error_msg}'
794
795
796class InvalidEndpointConfigurationError(BotoCoreError):
797 fmt = 'Invalid endpoint configuration: {msg}'
798
799
800class EndpointProviderError(BotoCoreError):
801 """Base error for the EndpointProvider class"""
802
803 fmt = '{msg}'
804
805
806class EndpointResolutionError(EndpointProviderError):
807 """Error when input parameters resolve to an error rule"""
808
809 fmt = '{msg}'
810
811
812class UnknownEndpointResolutionBuiltInName(EndpointProviderError):
813 fmt = 'Unknown builtin variable name: {name}'
814
815
816class InvalidChecksumConfigError(BotoCoreError):
817 """Error when an invalid checksum config value is supplied."""
818
819 fmt = (
820 'Unsupported configuration value for {config_key}. '
821 'Expected one of {valid_options} but got {config_value}.'
822 )
823
824
825class UnsupportedServiceProtocolsError(BotoCoreError):
826 """Error when a service does not use any protocol supported by botocore."""
827
828 fmt = (
829 'Botocore supports {botocore_supported_protocols}, but service {service} only '
830 'supports {service_supported_protocols}.'
831 )