{"id":"1d0df2b26ef77a09","repo":"pypa/pip","slug":"could-not-split-options-options-str","errorCode":null,"errorMessage":"Could not split options: {options_str}","messagePattern":"Could not split options: (.+?)","errorType":"exception","errorClass":"OptionParsingError","httpStatus":null,"severity":"error","filePath":"src/pip/_internal/req/req_file.py","lineNumber":442,"sourceCode":"\n\ndef get_line_parser(finder: PackageFinder | None) -> LineParser:\n    def parse_line(line: str) -> tuple[str, Values]:\n        # Build new parser for each line since it accumulates appendable\n        # options.\n        parser = build_parser()\n        defaults = parser.get_default_values()\n        defaults.index_url = None\n        if finder:\n            defaults.format_control = finder.format_control\n            defaults.release_control = finder.release_control\n\n        args_str, options_str = break_args_options(line)\n\n        try:\n            options = shlex.split(options_str)\n        except ValueError as e:\n            raise OptionParsingError(f\"Could not split options: {options_str}\") from e\n\n        opts, _ = parser.parse_args(options, defaults)\n\n        return args_str, opts\n\n    return parse_line\n\n\ndef break_args_options(line: str) -> tuple[str, str]:\n    \"\"\"Break up the line into an args and options string.  We only want to shlex\n    (and then optparse) the options, not the args.  args can contain markers\n    which are corrupted by shlex.\n    \"\"\"\n    tokens = line.split(\" \")\n    args = []\n    options = tokens[:]\n    for token in tokens:\n        if token.startswith((\"-\", \"--\")):","sourceCodeStart":424,"sourceCodeEnd":460,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_internal/req/req_file.py#L424-L460","documentation":"OptionParsingError raised inside get_line_parser when shlex.split(options_str) fails on the options portion of a requirements line. shlex raises ValueError on unbalanced quotes or other shell-lex errors, and pip re-raises as OptionParsingError which the file parser then turns into a RequirementsFileParseError. The full options substring is shown.","triggerScenarios":"A requirements line whose option part has an unmatched quote, e.g. 'pkg --find-links \"https://example.com' (missing closing quote), or an unescaped special character that shlex cannot tokenize. Triggered by 'pip install -r <file>'.","commonSituations":"Hand-editing a requirements file and dropping a closing quote; URL with a stray '\"'; copy-pasting from a rich-text source that converted quotes to smart quotes; whitespace inside an unquoted value.","solutions":["Locate the line in {options_str} (the error shows the offending substring) and balance all quotes.","Use '--opt=value' form (no spaces) to avoid shlex pitfalls for URLs with special characters.","Replace smart/curly quotes with straight ASCII quotes.","Re-run pip to confirm parsing succeeds."],"exampleFix":"# before\nrequests --find-links \"https://example.com/wheels\n\n# after\nrequests --find-links=https://example.com/wheels","handlingStrategy":"validation","validationCode":"import shlex\ndef options_split_ok(options_str: str) -> bool:\n    try:\n        shlex.split(options_str)\n        return True\n    except ValueError:\n        return False","typeGuard":"def is_shlex_safe(options_str: str) -> bool:\n    return options_split_ok(options_str)","tryCatchPattern":"import shlex\ntry:\n    shlex.split(options_str)\nexcept ValueError as e:\n    print(f'unbalanced quotes in: {options_str}'); raise\nrun_pip(['install', '-r', 'requirements.txt'])","preventionTips":["Always close quotes on requirement lines with URLs.","Use '--opt=value' (no spaces) to sidestep shlex entirely.","Strip smart quotes when pasting from rich text."],"tags":["requirements-file","parsing","shlex","config"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}