{"record":{"id":"eae784308a09ffc5","repo":"moeru-ai/airi","slug":"invalid-accelerator-input-multiple-non-modif","errorCode":null,"errorMessage":"Invalid accelerator \"${input}\": multiple non-modifier keys (\"${key}\", \"${token}\")","messagePattern":"Invalid accelerator \"(.+?)\": multiple non-modifier keys \\(\"(.+?)\", \"(.+?)\"\\)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/stage-shared/src/global-shortcut/accelerators.ts","lineNumber":335,"sourceCode":"  const rawTokens = trimmed.split('+')\n  const modifiers: ShortcutModifier[] = []\n  let key: ShortcutKey | undefined\n\n  for (const raw of rawTokens) {\n    const token = raw.trim()\n    if (token.length === 0)\n      throw new Error(`Invalid accelerator \"${input}\": empty token`)\n\n    const modifier = lookupModifierToken(token)\n    if (modifier !== undefined) {\n      if (modifiers.includes(modifier))\n        throw new Error(`Invalid accelerator \"${input}\": duplicate modifier \"${modifier}\"`)\n      modifiers.push(modifier)\n      continue\n    }\n\n    if (key !== undefined)\n      throw new Error(`Invalid accelerator \"${input}\": multiple non-modifier keys (\"${key}\", \"${token}\")`)\n    key = normalizeKeyToken(token)\n  }\n\n  if (key === undefined)\n    throw new Error(`Invalid accelerator \"${input}\": no key token`)\n\n  return { modifiers, key }\n}\n\n/**\n * Tests whether `input` is a well-formed accelerator string.\n *\n * Use when:\n * - Gating user input without needing the parsed result\n *\n * Returns:\n * - `true` when `parseAccelerator` would succeed, `false` otherwise\n */","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/stage-shared/src/global-shortcut/accelerators.ts#L317-L353","documentation":"Thrown by parseAccelerator when more than one non-modifier key token is present. An accelerator must end with exactly one main key; the parser records the first non-modifier token in `key` and throws as soon as a second one appears. Input like 'Ctrl+A+B' or 'Shift+F1+F2' is rejected.","triggerScenarios":"Calling parseAccelerator('Ctrl+A+B'), parseAccelerator('A B'), or passing a chord/sequence ('Ctrl+K Ctrl+S' style) where two key tokens end up joined with '+' instead of separated as a sequence.","commonSituations":"Trying to express VS Code-style key chords in a single accelerator string; concatenating a previously parsed key back onto a new binding ('Ctrl+' + 'A' + 'B'); capture UI that records two taps of letter keys without clearing the key slot between them.","solutions":["Split multi-key chords into separate accelerators and handle sequencing yourself; each accelerator string keeps exactly one key token","If concatenating strings, ensure only the final segment is a key — treat earlier segments as modifiers only","Validate with isValidAccelerator(input) before saving user bindings","In capture UI, reset the recorded key slot on each new non-modifier keydown"],"exampleFix":"// before\nparseAccelerator('Ctrl+K Ctrl+S')   // second token after space also fails\nparseAccelerator('Ctrl+K+S')         // throws: multiple non-modifier keys\n\n// after\n// model chords as an ordered list of accelerators\nconst chord = [parseAccelerator('Ctrl+K'), parseAccelerator('Ctrl+S')]","handlingStrategy":"validation","validationCode":"import { isValidAccelerator } from '../global-shortcut/accelerators'\n\nif (!isValidAccelerator(candidate)) {\n  // reject or treat as chord sequence, e.g. split on space and validate each part\n  const parts = candidate.split(/\\s+/)\n  if (!parts.every(isValidAccelerator)) return null\n}","typeGuard":null,"tryCatchPattern":"catch (e) { if (e instanceof Error && e.message.includes('multiple non-modifier keys')) return splitIntoChord(input); throw e }","preventionTips":["Model key chords as arrays of single-key accelerators, never one joined string","Reset the captured key slot on every new non-modifier keydown","Never append a second key token to an existing binding string"],"tags":["keyboard-shortcut","accelerator","key-chord","input-validation"],"backgroundTag":"invalid-accelerator-string","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}