diff --git a/openhands/runtime/utils/bash.py b/openhands/runtime/utils/bash.py index 0dc2bb451e..4e48697309 100644 --- a/openhands/runtime/utils/bash.py +++ b/openhands/runtime/utils/bash.py @@ -25,7 +25,7 @@ def split_bash_commands(commands: str) -> list[str]: return [''] try: parsed = bashlex.parse(commands) - except (bashlex.errors.ParsingError, NotImplementedError): + except (bashlex.errors.ParsingError, NotImplementedError, TypeError): logger.debug( f'Failed to parse bash commands\n' f'[input]: {commands}\n' @@ -145,7 +145,7 @@ def escape_bash_special_chars(command: str) -> str: remaining = command[last_pos:] parts.append(remaining) return ''.join(parts) - except (bashlex.errors.ParsingError, NotImplementedError): + except (bashlex.errors.ParsingError, NotImplementedError, TypeError): logger.debug( f'Failed to parse bash commands for special characters escape\n' f'[input]: {command}\n' diff --git a/tests/unit/test_bash_parsing.py b/tests/unit/test_bash_parsing.py index 38ee0f221c..018118209a 100644 --- a/tests/unit/test_bash_parsing.py +++ b/tests/unit/test_bash_parsing.py @@ -155,6 +155,31 @@ def test_invalid_syntax(): assert split_bash_commands(input_command) == [input_command] +def test_unclosed_backtick(): + # This test reproduces issue #7391 + # The issue occurs when parsing a command with an unclosed backtick + # which causes a TypeError: ParsingError.__init__() missing 2 required positional arguments: 's' and 'position' + command = 'echo `unclosed backtick' + + # Should not raise TypeError + try: + result = split_bash_commands(command) + # If we get here, the error was handled properly + assert result == [command] + except TypeError as e: + # This is the error we're trying to fix + raise e + + # Also test with the original command from the issue (with placeholder org/repo) + curl_command = 'curl -X POST "https://api.github.com/repos/example-org/example-repo/pulls" \\ -H "Authorization: Bearer $GITHUB_TOKEN" \\ -H "Accept: application/vnd.github.v3+json" \\ -d \'{ "title": "XXX", "head": "XXX", "base": "main", "draft": false }\' `echo unclosed' + + try: + result = split_bash_commands(curl_command) + assert result == [curl_command] + except TypeError as e: + raise e + + @pytest.fixture def sample_commands(): return [