kovidgoyal/kitty · error · ValueError

Unknown action in option `notify_on_cmd_finish`: {action}

Error message

Unknown action in option `notify_on_cmd_finish`: {action}

What it means

When a command finishes, kitty walks the notify_on_cmd_finish option's comma-separated actions; unrecognized tokens fall through to a ValueError naming the bad action. Valid actions include 'notify', 'notify-bell', and 'command' (the latter with a notify_cmdline configured). Anything else — including misspellings and unsupported names — is rejected.

Source

Thrown at kitty/window.py:1930

                if window.last_cmd_end_notification is not None:
                    if 'next' in opts.notify_on_cmd_finish.clear_on:
                        nm.close_notification(window.last_cmd_end_notification[0])
                    window.last_cmd_end_notification = None
                notification_id = nm.notify_with_command(cmd, window.id)
                if notification_id is not None:
                    window.last_cmd_end_notification = notification_id, cmd.only_when

            if action == 'notify':
                notify(self, opts, nm)
            elif action == 'bell':
                self.screen.bell()
            elif action == 'notify-bell':
                notify(self, opts, nm)
                self.screen.bell()
            elif action == 'command':
                open_cmd([x.replace('%c', self.last_cmd_cmdline).replace('%s', exit_status) for x in notify_cmdline])
            else:
                raise ValueError(f'Unknown action in option `notify_on_cmd_finish`: {action}')

    def cmd_output_marking(self, is_start: bool | None, cmdline: str = '') -> None:
        if is_start:
            start_time = monotonic()
            self.last_cmd_output_start_time = start_time
            cmdline = decode_cmdline(cmdline) if cmdline else ''
            self.last_cmd_cmdline = cmdline
            self.call_watchers(self.watchers.on_cmd_startstop, {'is_start': True, 'time': start_time, 'cmdline': cmdline, 'exit_status': 0})
        else:
            self.handle_cmd_end(cmdline)

    # }}}

    # mouse actions {{{
    @ac(
        'mouse',
        """
        Handle a mouse click

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Use only supported actions: notify, notify-bell, command
  2. Check the option's docs for your kitty version (actions differ across releases)
  3. Remove the unknown token from kitty.conf / the set-option call

Example fix

# before
notify_on_cmd_finish sound
# after
notify_on_cmd_finish notify
Defensive patterns

Strategy: validation

Validate before calling

VALID = {'notify', 'notify-bell', 'command'}
actions = [a for a in raw.split(',') if a]
bad = [a for a in actions if a not in VALID]
if bad:
    raise ValueError(f'unsupported notify actions: {bad}')

Type guard

def valid_notify_actions(value: str) -> bool:
    return all(a in ('notify', 'notify-bell', 'command') for a in value.split(',') if a)

Try / catch

try:
    opts.notify_on_cmd_finish = raw
except ValueError as e:
    if 'Unknown action' in str(e):
        opts.notify_on_cmd_finish = 'notify'
    else:
        raise

Prevention

When it happens

Trigger: Setting notify_on_cmd_finish to something like 'sound' or 'bell' (not 'notify-bell'), or a stray token like 'notify,' trailing comma artifacts producing an empty/garbage action.

Common situations: kitty.conf typos; copying config snippets from outdated docs or other terminals (e.g. trying 'bell' from a different option); version differences where an action name was renamed or not yet available.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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