Skip to content

Commit d55cb3d

Browse files
Standardized aws: [ERROR]: format for all CLI error messages (#9889)
* Implement standardized aws: [ERROR]: format for all CLI error messages * Add changelog entry for standardized error output
1 parent 57d9d66 commit d55cb3d

29 files changed

+206
-167
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"type": "enhancement",
3+
"category": "Error Messages",
4+
"description": "Standardize CLI error message format to use `aws: [ERROR]: <message>` prefix for consistency across all error types."
5+
}

awscli/argparser.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import copy
1515
import sys
1616
from difflib import get_close_matches
17+
from awscli.errorformat import format_error_message
1718

1819
HELP_BLURB = (
1920
"To see help text, you can run:\n"
@@ -113,7 +114,7 @@ def error(self, message):
113114
should raise an exception.
114115
"""
115116
usage_message = self.format_usage()
116-
error_message = f'{self.prog}: [ERROR]: {message}'
117+
error_message = format_error_message(message, prog=self.prog)
117118
raise ArgParseException(f'{error_message}\n\n{usage_message}')
118119

119120

awscli/customizations/configure/mfalogin.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from awscli.customizations.commands import BasicCommand
2525
from awscli.customizations.configure import profile_to_section
2626
from awscli.customizations.configure.writer import ConfigFileWriter
27+
from awscli.errorformat import write_error
2728

2829
LOG = logging.getLogger(__name__)
2930

@@ -142,7 +143,7 @@ def _get_mfa_token(self):
142143
'None', 'mfa_token', 'MFA token code'
143144
)
144145
if not token_code:
145-
sys.stderr.write("MFA token code is required\n")
146+
write_error(sys.stderr, "MFA token code is required")
146147
return None
147148
return token_code
148149

@@ -156,7 +157,7 @@ def _call_sts_get_session_token(self, sts_client, duration_seconds, mfa_serial,
156157
)
157158
return response
158159
except ClientError as e:
159-
sys.stderr.write(f"An error occurred: {e}\n")
160+
write_error(sys.stderr, f"An error occurred: {e}")
160161
return None
161162

162163
def _resolve_mfa_serial(self, parsed_args, source_config):
@@ -167,7 +168,7 @@ def _resolve_mfa_serial(self, parsed_args, source_config):
167168
'None', 'mfa_serial', 'MFA serial number or ARN'
168169
)
169170
if not mfa_serial:
170-
sys.stderr.write("MFA serial number or MFA device ARN is required\n")
171+
write_error(sys.stderr, "MFA serial number or MFA device ARN is required")
171172
return None
172173
return mfa_serial
173174

@@ -252,7 +253,7 @@ def _handle_interactive_prompting(self, parsed_args, duration_seconds):
252253
'None', config_name, prompt_text
253254
)
254255
if not value or value == 'None':
255-
sys.stderr.write(f"{prompt_text} is required\n")
256+
write_error(sys.stderr, f"{prompt_text} is required")
256257
return 1
257258
values[config_name] = value
258259

awscli/customizations/ecs/exceptions.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,26 @@ def __init__(self, **kwargs):
2424

2525

2626
class MissingPropertyError(ECSError):
27-
fmt = "Error: Resource '{resource}' must include property '{prop_name}'"
27+
fmt = "Resource '{resource}' must include property '{prop_name}'"
2828

2929

3030
class FileLoadError(ECSError):
31-
fmt = "Error: Unable to load file at {file_path}: {error}"
31+
fmt = "Unable to load file at {file_path}: {error}"
3232

3333

3434
class InvalidPlatformError(ECSError):
35-
fmt = "Error: {resource} '{name}' must support 'ECS' compute platform"
35+
fmt = "{resource} '{name}' must support 'ECS' compute platform"
3636

3737

3838
class InvalidProperyError(ECSError):
3939
fmt = (
40-
"Error: deployment group '{dg_name}' does not target "
40+
"deployment group '{dg_name}' does not target "
4141
"ECS {resource} '{resource_name}'"
4242
)
4343

4444

4545
class InvalidServiceError(ECSError):
46-
fmt = "Error: Service '{service}' not found in cluster '{cluster}'"
46+
fmt = "Service '{service}' not found in cluster '{cluster}'"
4747

4848

4949
class ServiceClientError(ECSError):

awscli/customizations/emr/applicationutils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def build_applications(region, parsed_applications, ami_version=None):
6262
)
6363
else:
6464
raise ParamValidationError(
65-
'aws: error: AMI version %s is not '
65+
'AMI version %s is not '
6666
'compatible with HBase.' % ami_version
6767
)
6868
elif app_name == constants.IMPALA:

awscli/customizations/emr/createcluster.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ def _run_main_command(self, parsed_args, parsed_globals):
293293
)
294294
except ValueError:
295295
raise ParamValidationError(
296-
'aws: error: invalid json argument for '
296+
'invalid json argument for '
297297
'option --configurations'
298298
)
299299

@@ -697,7 +697,7 @@ def _build_bootstrap_actions(self, cluster, parsed_boostrap_actions):
697697
> constants.MAX_BOOTSTRAP_ACTION_NUMBER
698698
):
699699
raise ParamValidationError(
700-
'aws: error: maximum number of '
700+
'maximum number of '
701701
'bootstrap actions for a cluster exceeded.'
702702
)
703703

awscli/customizations/emr/emrutils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def apply_boolean_options(
6060
):
6161
if true_option and false_option:
6262
error_message = (
63-
'aws: error: cannot use both '
63+
'cannot use both '
6464
+ true_option_name
6565
+ ' and '
6666
+ false_option_name

awscli/customizations/emr/exceptions.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class MissingParametersError(EmrError, ParamValidationError):
4141
"""
4242

4343
fmt = (
44-
'aws: error: The following required parameters are missing for '
44+
'The following required parameters are missing for '
4545
'{object_name}: {missing}.'
4646
)
4747

@@ -53,7 +53,7 @@ class EmptyListError(EmrError, ParamValidationError):
5353
:ivar param: The provided list parameter
5454
"""
5555

56-
fmt = 'aws: error: The prameter {param} cannot be an empty list.'
56+
fmt = 'The prameter {param} cannot be an empty list.'
5757

5858

5959
class MissingRequiredInstanceGroupsError(EmrError, ParamValidationError):
@@ -63,7 +63,7 @@ class MissingRequiredInstanceGroupsError(EmrError, ParamValidationError):
6363
"""
6464

6565
fmt = (
66-
'aws: error: Must specify either --instance-groups or '
66+
'Must specify either --instance-groups or '
6767
'--instance-type with --instance-count(optional) to '
6868
'configure instance groups.'
6969
)
@@ -77,7 +77,7 @@ class InstanceGroupsValidationError(EmrError, ParamValidationError):
7777
"""
7878

7979
fmt = (
80-
'aws: error: You may not specify --instance-type '
80+
'You may not specify --instance-type '
8181
'or --instance-count with --instance-groups, '
8282
'because --instance-type and --instance-count are '
8383
'shortcut options for --instance-groups.'
@@ -91,7 +91,7 @@ class InvalidAmiVersionError(EmrError, ParamValidationError):
9191
"""
9292

9393
fmt = (
94-
'aws: error: The supplied AMI version "{ami_version}" is invalid.'
94+
'The supplied AMI version "{ami_version}" is invalid.'
9595
' Please see AMI Versions Supported in Amazon EMR in '
9696
'Amazon Elastic MapReduce Developer Guide: '
9797
'http://docs.aws.amazon.com/ElasticMapReduce/'
@@ -108,7 +108,7 @@ class MissingBooleanOptionsError(EmrError, ParamValidationError):
108108
"""
109109

110110
fmt = (
111-
'aws: error: Must specify one of the following boolean options: '
111+
'Must specify one of the following boolean options: '
112112
'{true_option}|{false_option}.'
113113
)
114114

@@ -120,7 +120,7 @@ class UnknownStepTypeError(EmrError, ParamValidationError):
120120
:ivar step_type: the step_type provided.
121121
"""
122122

123-
fmt = 'aws: error: The step type {step_type} is not supported.'
123+
fmt = 'The step type {step_type} is not supported.'
124124

125125

126126
class UnknownIamEndpointError(EmrError):
@@ -154,7 +154,7 @@ class LogUriError(EmrError, ParamValidationError):
154154
"""
155155

156156
fmt = (
157-
'aws: error: LogUri not specified. You must specify a logUri '
157+
'LogUri not specified. You must specify a logUri '
158158
'if you enable debugging when creating a cluster.'
159159
)
160160

@@ -212,7 +212,7 @@ class SubnetAndAzValidationError(EmrError, ParamValidationError):
212212
"""
213213

214214
fmt = (
215-
'aws: error: You may not specify both a SubnetId and an Availabili'
215+
'You may not specify both a SubnetId and an Availabili'
216216
'tyZone (placement) because ec2SubnetId implies a placement.'
217217
)
218218

@@ -222,7 +222,7 @@ class RequiredOptionsError(EmrError, ParamValidationError):
222222
Either of option1 or option2 is required.
223223
"""
224224

225-
fmt = 'aws: error: Either {option1} or {option2} is required.'
225+
fmt = 'Either {option1} or {option2} is required.'
226226

227227

228228
class MutualExclusiveOptionError(EmrError, ParamValidationError):
@@ -236,7 +236,7 @@ class MutualExclusiveOptionError(EmrError, ParamValidationError):
236236

237237
def __init__(self, **kwargs):
238238
msg = (
239-
'aws: error: You cannot specify both '
239+
'You cannot specify both '
240240
+ kwargs.get('option1', '')
241241
+ ' and '
242242
+ kwargs.get('option2', '')
@@ -256,7 +256,7 @@ class MissingApplicationsError(EmrError, ParamValidationError):
256256

257257
def __init__(self, **kwargs):
258258
msg = (
259-
'aws: error: Some of the steps require the following'
259+
'Some of the steps require the following'
260260
' applications to be installed: '
261261
+ ', '.join(kwargs['applications'])
262262
+ '. Please install the'
@@ -270,7 +270,7 @@ class ClusterTerminatedError(EmrError):
270270
The cluster is terminating or has already terminated.
271271
"""
272272

273-
fmt = 'aws: error: Cluster terminating or already terminated.'
273+
fmt = 'Cluster terminating or already terminated.'
274274

275275

276276
class ClusterStatesFilterValidationError(EmrError, ParamValidationError):
@@ -282,7 +282,7 @@ class ClusterStatesFilterValidationError(EmrError, ParamValidationError):
282282
"""
283283

284284
fmt = (
285-
'aws: error: You can specify only one of the cluster state '
285+
'You can specify only one of the cluster state '
286286
'filters: --cluster-states, --active, --terminated, --failed.'
287287
)
288288

@@ -296,7 +296,7 @@ class MissingClusterAttributesError(EmrError, ParamValidationError):
296296
"""
297297

298298
fmt = (
299-
'aws: error: Must specify one of the following boolean options: '
299+
'Must specify one of the following boolean options: '
300300
'--visible-to-all-users|--no-visible-to-all-users, '
301301
'--termination-protected|--no-termination-protected, '
302302
'--auto-terminate|--no-auto-terminate, '
@@ -314,14 +314,14 @@ class InvalidEmrFsArgumentsError(EmrError, ParamValidationError):
314314
"""
315315

316316
fmt = (
317-
'aws: error: {parent_object_name} is not specified. Thus, '
317+
'{parent_object_name} is not specified. Thus, '
318318
' following parameters are invalid: {invalid}'
319319
)
320320

321321

322322
class DuplicateEmrFsConfigurationError(EmrError, ParamValidationError):
323323
fmt = (
324-
'aws: error: EMRFS should be configured either using '
324+
'EMRFS should be configured either using '
325325
'--configuration or --emrfs but not both'
326326
)
327327

@@ -334,7 +334,7 @@ class UnknownCseProviderTypeError(EmrError, ParamValidationError):
334334
"""
335335

336336
fmt = (
337-
'aws: error: The client side encryption type "{provider_type}" is '
337+
'The client side encryption type "{provider_type}" is '
338338
'not supported. You must specify either KMS or Custom'
339339
)
340340

@@ -347,7 +347,7 @@ class UnknownEncryptionTypeError(EmrError, ParamValidationError):
347347
"""
348348

349349
fmt = (
350-
'aws: error: The encryption type "{encryption}" is invalid. '
350+
'The encryption type "{encryption}" is invalid. '
351351
'You must specify either ServerSide or ClientSide'
352352
)
353353

@@ -361,14 +361,14 @@ class BothSseAndEncryptionConfiguredError(EmrError, ParamValidationError):
361361
"""
362362

363363
fmt = (
364-
'aws: error: Both SSE={sse} and Encryption={encryption} are '
364+
'Both SSE={sse} and Encryption={encryption} are '
365365
'configured for --emrfs. You must specify only one of the two.'
366366
)
367367

368368

369369
class InvalidBooleanConfigError(EmrError, ParamValidationError):
370370
fmt = (
371-
"aws: error: {config_value} for {config_key} in the config file is "
371+
"{config_value} for {config_key} in the config file is "
372372
"invalid. The value should be either 'True' or 'False'. Use "
373373
"'aws configure set {profile_var_name}.emr.{config_key} <value>' "
374374
"command to set a valid value."
@@ -377,13 +377,13 @@ class InvalidBooleanConfigError(EmrError, ParamValidationError):
377377

378378
class UnsupportedCommandWithReleaseError(EmrError, ParamValidationError):
379379
fmt = (
380-
"aws: error: {command} is not supported with "
380+
"{command} is not supported with "
381381
"'{release_label}' release."
382382
)
383383

384384

385385
class MissingAutoScalingRoleError(EmrError, ParamValidationError):
386386
fmt = (
387-
"aws: error: Must specify --auto-scaling-role when configuring an "
387+
"Must specify --auto-scaling-role when configuring an "
388388
"AutoScaling policy for an instance group."
389389
)

awscli/customizations/emr/hbase.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ def _check_type(self, type):
129129
type = type.lower()
130130
if type != constants.FULL and type != constants.INCREMENTAL:
131131
raise ParamValidationError(
132-
'aws: error: invalid type. '
132+
'invalid type. '
133133
'type should be either '
134134
+ constants.FULL
135135
+ ' or '
@@ -145,7 +145,7 @@ def _check_unit(self, unit):
145145
and unit != constants.DAYS
146146
):
147147
raise ParamValidationError(
148-
'aws: error: invalid unit. unit should be one of'
148+
'invalid unit. unit should be one of'
149149
' the following values: '
150150
+ constants.MINUTES
151151
+ ', '

awscli/customizations/emr/installapplications.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,13 @@ def _check_for_supported_apps(self, parsed_applications):
6767
if app_name in constants.APPLICATIONS:
6868
if app_name not in self.supported_apps:
6969
raise ParamValidationError(
70-
"aws: error: " + app_config['Name'] + " cannot be"
70+
app_config['Name'] + " cannot be"
7171
" installed on a running cluster. 'Name' should be one"
7272
" of the following: " + ', '.join(self.supported_apps)
7373
)
7474
else:
7575
raise ParamValidationError(
76-
"aws: error: Unknown application: "
76+
"Unknown application: "
7777
+ app_config['Name']
7878
+ ". 'Name' should be one of the following: "
7979
+ ', '.join(constants.APPLICATIONS)

0 commit comments

Comments
 (0)