moeru-ai/airi · error · Error
Invalid accelerator: empty string
Error message
Invalid accelerator: empty string
What it means
`parseAccelerator(input)` parses a shortcut string like `"Mod+Shift+K"` into a structured `ShortcutAccelerator`. It throws `Invalid accelerator: empty string` when `input.trim()` has length 0, i.e. the caller passed `""`, `" "`, or a value that becomes empty after trimming. Parsing happens before any tokenization, so no other validation runs. Whitespace-only strings are treated identically to the empty string.
Source
Thrown at packages/stage-shared/src/global-shortcut/accelerators.ts:315
* canonical key
*
* Throws:
* - `Error` when the input is empty, has empty tokens, names an
* unknown key, repeats a modifier, or contains multiple non-modifier
* tokens
*
* @example
* parseAccelerator('Mod+Shift+K')
* // => { modifiers: ['cmd-or-ctrl', 'shift'], key: 'KeyK' }
*
* @example
* parseAccelerator(' CmdOrCtrl + Shift + KeyK ')
* // => same as above; whitespace tolerated
*/
export function parseAccelerator(input: string): ShortcutAccelerator {
const trimmed = input.trim()
if (trimmed.length === 0)
throw new Error('Invalid accelerator: empty string')
const rawTokens = trimmed.split('+')
const modifiers: ShortcutModifier[] = []
let key: ShortcutKey | undefined
for (const raw of rawTokens) {
const token = raw.trim()
if (token.length === 0)
throw new Error(`Invalid accelerator "${input}": empty token`)
const modifier = lookupModifierToken(token)
if (modifier !== undefined) {
if (modifiers.includes(modifier))
throw new Error(`Invalid accelerator "${input}": duplicate modifier "${modifier}"`)
modifiers.push(modifier)
continue
}
View on GitHub (pinned to 27111382b4)
Solutions
- Guard the input before parsing: `if (!input?.trim()) return` or use the provided `isValidAccelerator(input)` / `tryParseAccelerator` helper if available.
- Treat an empty binding as 'no shortcut' in your settings model (store `null` rather than `''`).
- Validate in the settings UI: disable the save/apply action while the field is empty.
- If parsing user input live, skip the `parseAccelerator` call until the string is non-empty.
Example fix
// before const acc = parseAccelerator(settings.globalShortcut ?? '') // after const raw = settings.globalShortcut if (!raw || !raw.trim()) return // treat as unbound const acc = parseAccelerator(raw)
Defensive patterns
Strategy: validation
Validate before calling
function shouldParseAccelerator(input: unknown): input is string {
return typeof input === 'string' && input.trim().length > 0
}
if (shouldParseAccelerator(raw)) parseAccelerator(raw) Type guard
function isNonEmptyAcceleratorString(input: unknown): input is string {
return typeof input === 'string' && input.trim().length > 0
} Try / catch
try {
const acc = parseAccelerator(raw)
} catch (e) {
if (e instanceof Error && e.message.startsWith('Invalid accelerator')) {
// treat as unbound; do not register
} else throw e
} Prevention
- Store unbound shortcuts as null, not empty string.
- Run isValidAccelerator(input) on any user-supplied keybind before parse.
- Disable the apply/save action in the UI while the field is empty.
When it happens
Trigger: Calling `parseAccelerator('')`, `parseAccelerator(' ')`, or passing a variable that resolved to an empty/whitespace string (e.g. a settings field that was never filled in, a form input before the user typed anything, or a destructured config value that defaulted to `''`).
Common situations: Loading a global-shortcut binding from persisted settings where the field was saved blank; binding a keybind editor to a reactive ref before the user enters a value; reading a YAML/JSON config key that is present but empty; passing `undefined`-derived defaults that coerce to `''`.
Related errors
- Invalid accelerator "${input}": empty token
- Invalid accelerator "${input}": duplicate modifier "${modifi
- Invalid accelerator "${input}": multiple non-modifier keys (
- Invalid accelerator "${input}": no key token
- Invalid accelerator: unknown key "${token}"
AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12).
Data as JSON: /api/errors/227b0398962d7693.
Report an issue: GitHub.