Skip to content

Confusing error message when options for python are erroneously quoted #132414

Description

@za3k

Bug report

Bug description:

#!/bin/python -q -i

I was writing an unrelated post about shebang lines tricks+tips, and happened to pick python as an example, only to discover some weird behavior. The above gets parsed as /bin/python "-q -i" <path/to/script>

But the message python prints is quite confusing:

Unknown option: - 
usage: python [option] ... [-c cmd | -m mod | file | -] [arg] ...
Try `python -h' for more information.

What's happening is that the "unknown option" is a single space, being parsed as a short-form option, and printed. But the output is pretty opaque, since the space is not quoted, and it's just a trailing invisible space.

Aside: Several other invalid one-byte options like \n get printed wrongly. This doesn't seem worth fixing.


Proposed fix:

I think the shebang case happens to users often enough that it would be good to have some kind of better error message if a short-form options list contains either of

  • - (this would require scanning ahead!), which either indicates some quoting problem, or an incorrect long-form option (-check-hash-based-pycs rather than --check-hash-based-pycs).

I think a good error message could be unknown option: -q -i or unknown option: "-q -i". Quoting the argument when it contains a space seems clearer to me.

The current long-form options have pretty clear error messages either way, mostly by happenstance.

Currently, -help-* parses as -h which then prints help, stopping option parsing. I have no strong opinion about whether that behavior is better or worse than printing an error message.

CPython versions tested on:

3.13

Operating systems tested on:

Linux

Linked PRs

Activity

  1. added
    type-bugAn unexpected behavior, bug, or error
    on Apr 11, 2025
  2. picnixz commented on Apr 11, 2025

    @picnixz
    Member

    What's the behavior of other CLIs like ls, cp, etc in this case?

  3. changed the title [-]Confusing error message when options are erroneously quoted[/-] [+]Confusing error message when options for `python` are erroneously quoted[/+] on Apr 11, 2025
  4. za3k commented on Apr 11, 2025

    @za3k
    Author

    Oh, sensible question.

    $ ls "-l -a"
    ls: invalid option -- ' '
    $ ls "-q"
    ls: invalid option -- 'q'
    $ ls -a-s-d
    ls: invalid option -- '-'
    $ ls --a-sdsd
    ls: unrecognized option '--a-sdsd'
    $ cp "-v -v"
    cp: invalid option -- ' '
    
    $ which "-a -a" # note: zsh builtin
    which: bad option: - 
    
    $ /bin/which "-a -a"
    /bin/which: invalid option -- ' '
    /bin/which: invalid option -- '-'
    
    $ perl "-p -u"
    perl # unquotes the argument and executes normally
    

    GNU coreutils programs like cp and ls use seem to unconditionally quote the argument. cp and ls print the first failure, which seems to print all of them.

    zsh's which builtin matches python behavior. Note that it doesn't support long-form options.

    perl is doing its own thing.

  5. picnixz commented on Apr 14, 2025

    @picnixz
    Member

    I think we should follow GNU coreutils as we would have less ambiguities, namely "invalid option -- '<FAILURE>'".

    Let's hear the opinion of people who worked on some accessibility REPL issues @hugovk @pablogsal @serhiy-storchaka

  6. hugovk commented on Apr 16, 2025

    @hugovk
    Member

    I think GNU coreutils is an okay default, but can we do better?

    invalid option -- doesn't really tell me anything about what I need to do to get it working. Can we give an actionable message?

    Or is it safe to act like perl and unquote the arguments and execute normally?


    btw I use https://github.com/lsd-rs/lsd as an alias for ls and it tries to be more useful, but doesn't really help:

    ❯ ls "-l -a"
    error: unexpected argument '- ' found
    
      tip: to pass '- ' as a value, use '-- - '
    
    Usage: lsd [OPTIONS] [FILE]...
    
  7. serhiy-storchaka commented on Apr 16, 2025

    @serhiy-storchaka
    Member

    An actionable message is just a guess. It can be correct, it can be wrong. This is not common issue, and we cannot be sure that special message will be helpful and not add more confusion.

    Acting like perl is unsafe. If the guess is not correct, it will silently do wrong things instead of just printing (possibly unclear) message.

  8. pablogsal commented on Apr 16, 2025

    @pablogsal
    Member

    I agree with @serhiy-storchaka

  9. za3k commented on Apr 16, 2025

    @za3k
    Author

    Right, to summarize (there are a lot of thumbs-ups) everyone asked is in agreement to follow the coreutils example of

    /bin/python: invalid option -- '<FAILURE>'
    

    Although both of the following have some of the same virtues for the same input

    /bin/python: invalid option -- ' '
    /bin/python: invalid option -- '-q -i'
    

    I'm pretty sure we prefer the exact option coreutils uses (the first), and which has therefore been (1) tested for a few decades and (2) will be familiar to users.

  10. vasiliyk commented on Sep 21, 2026

    @vasiliyk
    Contributor

    I've opened the PR implementing the coreutils style agreed above.

    Short options print Invalid option -- 'X'.
    Long options print Invalid option '--name', without the separator, as coreutils does.

    $ python "-q -i"
    Invalid option -- ' '
    
    $ python --foo
    Invalid option '--foo'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions