diff --git a/arrow/parser.py b/arrow/parser.py index fc3774b0..d0d7abce 100644 --- a/arrow/parser.py +++ b/arrow/parser.py @@ -422,12 +422,21 @@ def parse( parts: _Parts = {} for token in fmt_tokens: value: Union[Tuple[str, str, str], str] - if token == "Do": - value = match.group("value") - elif token == "W": - value = (match.group("year"), match.group("week"), match.group("day")) - else: - value = match.group(token) + try: + if token == "Do": + value = match.group("value") + elif token == "W": + value = ( + match.group("year"), + match.group("week"), + match.group("day"), + ) + else: + value = match.group(token) + except IndexError: + raise ParserMatchError( + f"Failed to match {fmt!r} when parsing {datetime_string!r}." + ) if value is None: raise ParserMatchError( diff --git a/tests/test_parser.py b/tests/test_parser.py index 7038d880..4b41a711 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -779,6 +779,15 @@ def test_parse_normalize_whitespace(self): with pytest.raises(ParserError): self.parser.parse(" \n Jun 1\t 2005\n ", "MMM D YYYY") + def test_parse_malformed_fmt_no_indexerror(self): + """Malformed format strings should raise ParserMatchError, not IndexError.""" + with pytest.raises(ParserMatchError): + self.parser.parse( + "foo", + "[-FFFFFFFFFFFFFFFFFFFFF-[-FFFFFFFFFFFF" + "[ |||||||| 7 v.dG(dG\\][3zasks &", + ) + @pytest.mark.usefixtures("dt_parser_regex") class TestDateTimeParserRegex: