{"record":{"id":"138d7b542cef7021","repo":"neoclide/coc.nvim","slug":"invalid-key-name-of-registerkeymap","errorCode":null,"errorMessage":"Invalid key ${name} of registerKeymap","messagePattern":"Invalid key (.+?) of registerKeymap","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/core/keymaps.ts","lineNumber":77,"sourceCode":"    if (res == null) return defaultReturn\n    return res as string\n  }\n\n  public async doInsertKeymap(key: string, ...args: any[]): Promise<InsertKeymapResult> {\n    let fn = this.insertKeymaps.get(key)\n    if (!fn) {\n      logger.error(`insert keymap for ${key} not found`)\n      return []\n    }\n    let res = await Promise.resolve(fn(...args))\n    return Array.isArray(res) ? res : []\n  }\n\n  /**\n   * Register global <Plug>(coc-${key}) key mapping.\n   */\n  public registerKeymap(modes: MapMode[], name: string, fn: KeymapCallback, opts: KeymapOption = {}): Disposable {\n    if (!name) throw new Error(`Invalid key ${name} of registerKeymap`)\n    let key = `coc-${name}`\n    if (this.keymaps.has(key)) throw new Error(`keymap: \"${name}\" already exists.`)\n    const lhs = `<Plug>(${key})`\n    opts = Object.assign({ sync: true, cancel: true, silent: true, repeat: false }, opts)\n    let { nvim } = this\n    this.keymaps.set(key, [fn, !!opts.repeat])\n    let method = opts.sync ? 'request' : 'notify'\n    for (let mode of modes) {\n      if (mode == 'i') {\n        const cancel = opts.cancel ? 1 : 0\n        nvim.setKeymap(mode, lhs, `coc#_insert_key('${method}', '${key}', ${cancel})`, {\n          expr: true,\n          noremap: true,\n          silent: opts.silent\n        })\n      } else {\n        nvim.setKeymap(mode, lhs, `:${getKeymapModifier(mode, opts.cmd)}call coc#rpc#${method}('doKeymap', ['${key}'])<cr>`, {\n          noremap: true,","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/neoclide/coc.nvim/blob/50e974d9692461a69147d5cab146a8d3e439abe4/src/core/keymaps.ts#L59-L95","documentation":"registerKeymap requires a non-empty name because it generates a global <Plug>(coc-<name>) mapping. An empty/falsy name cannot form a valid mapping, so registration throws immediately.","triggerScenarios":"Calling keymaps.registerKeymap(['n'], '', fn) or with a variable that is undefined due to a bad import/config.","commonSituations":"Extension keymap registration built from dynamic values that resolve to empty strings; copy-pasted registration code missing the name argument.","solutions":["Pass a non-empty name string to registerKeymap","Fix the dynamic value used as the keymap name","Validate inputs before calling the API"],"exampleFix":"// before\nkeymaps.registerKeymap(['n'], name, fn) // name === ''\n// after\nif (!name) return\nkeymaps.registerKeymap(['n'], name, fn)","handlingStrategy":"validation","validationCode":"const valid = typeof name === 'string' && name.length > 0\nif (!valid) throw new TypeError('keymap name must be a non-empty string')","typeGuard":"const isValidKeymapName = (n): n is string => typeof n === 'string' && n.length > 0","tryCatchPattern":"try {\n  keymaps.registerKeymap(['n'], name, handler)\n} catch (e) {\n  if (String(e.message).startsWith('Invalid key')) logger.error(`bad keymap name: ${JSON.stringify(name)}`)\n  else throw e\n}","preventionTips":["Type name parameters as string so empty/undefined fails at compile time","Avoid dynamic names from possibly-empty config values","Test extension activation to catch empty names early"],"tags":["keymap","validation","api-misuse"],"backgroundTag":"invalid-argument","analyzedSha":"50e974d9692461a69147d5cab146a8d3e439abe4","analyzedAt":"2026-08-31T11:17:23.966Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}