diff --git a/httpie/cli/argparser.py b/httpie/cli/argparser.py index 9bf09b3b73..fb4111170c 100644 --- a/httpie/cli/argparser.py +++ b/httpie/cli/argparser.py @@ -555,7 +555,12 @@ def _process_format_options(self): format_options = self.args.format_options or [] parsed_options = PARSED_DEFAULT_FORMAT_OPTIONS for options_group in format_options: - parsed_options = parse_format_options(options_group, defaults=parsed_options) + try: + parsed_options = parse_format_options(options_group, defaults=parsed_options) + except argparse.ArgumentTypeError as e: + if self.args.traceback: + raise + self.error(f'--format-options: {e.args[0]}') self.args.format_options = parsed_options def print_manual(self): diff --git a/tests/test_output.py b/tests/test_output.py index 2242177dbc..176cbe25c3 100644 --- a/tests/test_output.py +++ b/tests/test_output.py @@ -450,6 +450,35 @@ def test_parse_format_options_errors(self, options_string, expected_error): with pytest.raises(argparse.ArgumentTypeError, match=expected_error): parse_format_options(s=options_string, defaults=defaults) + @pytest.mark.parametrize( + 'options_string, expected_error', + [ + ('json', 'invalid option'), + ('json.nope:1', 'invalid key'), + ('json.indent:nope', "invalid value 'nope'"), + ] + ) + def test_invalid_format_options_are_reported_as_cli_errors( + self, options_string, expected_error + ): + # An invalid --format-options value must produce a regular CLI error, + # not an unhandled `argparse.ArgumentTypeError` traceback. + r = unhandled = None + try: + r = http( + '--offline', f'--format-options={options_string}', DUMMY_URL, + tolerate_error_exit_status=True, + ) + except Exception as exc: # noqa: BLE001 + unhandled = exc + + assert unhandled is None, ( + f'unhandled {type(unhandled).__name__}: {unhandled}' + ) + assert r.exit_status == ExitStatus.ERROR + assert '--format-options' in r.stderr + assert expected_error in r.stderr + @pytest.mark.parametrize( 'args, expected_format_options', [