kovidgoyal/kitty · error · SystemExit

Unknown extra argument(s) supplied to

Error message

Unknown extra argument(s) supplied to {command.name}

What it means

SystemExit raised while parsing a kitty remote-control subcommand's CLI when the command accepts zero positional arguments but one or more were supplied. parse_subcommand_cli compares command.args.args_count (0) against the number of leftover items after option parsing and aborts with this message.

Solutions

  1. Remove the extra positional argument(s)
  2. Move the value to its proper option flag, e.g. --match or --title, per the command's --help
  3. Quote multi-word values so the shell doesn't split them into extra positionals

Example fix

# before
kitten @ close-window all

# after
kitten @ close-window --match state=recent
Defensive patterns

Strategy: validation

Validate before calling

# zero-arg commands: strip positionals before invoking
zero_arg = {'close-window', 'close-tab', 'detach-window'}
if cmd in zero_arg:
    positionals = []
run = ['kitten', '@', cmd, *options, *positionals]

Type guard

def takes_positionals(cmd: str) -> bool:
    return cmd not in {'close-window', 'close-tab', 'detach-window', 'load-config'}  # maintain per your command set

Try / catch

res = subprocess.run(cmd, capture_output=True, text=True)
if 'Unknown extra argument(s)' in res.stderr:
    cmd = cmd[:3] + cmd[3:-1]  # drop trailing positional and retry once
    res = subprocess.run(cmd, capture_output=True, text=True)

Prevention

When it happens

Trigger: Running e.g. 'kitten @ close-window extra-arg' or 'kitten @ set-tab-title foo' style commands that take no positional args with trailing arguments; also triggered by unquoted arguments that the shell splits.

Common situations: Copy-pasting command lines with leftover placeholders, passing a value that should be an option (--match) as a positional, or shell expansion adding extra words.

Related errors


AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27). Data as JSON: /api/errors/a84dc0ec18d4b089. Report an issue: GitHub.

Appendix: source

Thrown at kitty/rc/base.py:452

    def cancel_async_request(self, boss: 'Boss', window: Optional['Window'], payload_get: PayloadGetType) -> None:
        pass

    def handle_streamed_data(self, data: bytes, payload_get: PayloadGetType) -> BytesIO | AsyncResponse:
        stream_id = payload_get('stream_id')
        if not stream_id or not isinstance(stream_id, str):
            raise StreamError('No stream_id in rc payload')
        return self.stream_in_flight.handle_data(stream_id, data)


def cli_params_for(command: RemoteCommand) -> tuple[Callable[[], str], str, str, str]:
    return (command.options_spec or '\n').format, command.args.spec, command.desc, f'kitten @ {command.name}'


def parse_subcommand_cli(command: RemoteCommand, args: ArgsType) -> tuple[Any, ArgsType]:
    opts, items = parse_args(args[1:], *cli_params_for(command), result_class=command.options_class)
    if command.args.args_count is not None and command.args.args_count != len(items):
        if command.args.args_count == 0:
            raise SystemExit(f'Unknown extra argument(s) supplied to {command.name}')
        raise SystemExit(f'Must specify exactly {command.args.args_count} argument(s) for {command.name}')
    return opts, items


def display_subcommand_help(func: RemoteCommand) -> None:
    with suppress(SystemExit):
        parse_args(['--help'], (func.options_spec or '\n').format, func.args.spec, func.desc, func.name)


def command_for_name(cmd_name: str) -> RemoteCommand:
    from importlib import import_module

    cmd_name = cmd_name.replace('-', '_')
    try:
        m = import_module(f'kitty.rc.{cmd_name}')
    except ImportError:
        raise KeyError(f'Unknown kitty remote control command: {cmd_name}')
    return cast(RemoteCommand, getattr(m, cmd_name))

View on GitHub (pinned to 6d5d0c4406)