neoclide/coc.nvim · error
Invalid key ${name} of registerKeymap
Error message
Invalid key ${name} of registerKeymap What it means
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.
Source
Thrown at src/core/keymaps.ts:77
if (res == null) return defaultReturn
return res as string
}
public async doInsertKeymap(key: string, ...args: any[]): Promise<InsertKeymapResult> {
let fn = this.insertKeymaps.get(key)
if (!fn) {
logger.error(`insert keymap for ${key} not found`)
return []
}
let res = await Promise.resolve(fn(...args))
return Array.isArray(res) ? res : []
}
/**
* Register global <Plug>(coc-${key}) key mapping.
*/
public registerKeymap(modes: MapMode[], name: string, fn: KeymapCallback, opts: KeymapOption = {}): Disposable {
if (!name) throw new Error(`Invalid key ${name} of registerKeymap`)
let key = `coc-${name}`
if (this.keymaps.has(key)) throw new Error(`keymap: "${name}" already exists.`)
const lhs = `<Plug>(${key})`
opts = Object.assign({ sync: true, cancel: true, silent: true, repeat: false }, opts)
let { nvim } = this
this.keymaps.set(key, [fn, !!opts.repeat])
let method = opts.sync ? 'request' : 'notify'
for (let mode of modes) {
if (mode == 'i') {
const cancel = opts.cancel ? 1 : 0
nvim.setKeymap(mode, lhs, `coc#_insert_key('${method}', '${key}', ${cancel})`, {
expr: true,
noremap: true,
silent: opts.silent
})
} else {
nvim.setKeymap(mode, lhs, `:${getKeymapModifier(mode, opts.cmd)}call coc#rpc#${method}('doKeymap', ['${key}'])<cr>`, {
noremap: true,View on GitHub (pinned to 50e974d969)
Solutions
- Pass a non-empty name string to registerKeymap
- Fix the dynamic value used as the keymap name
- Validate inputs before calling the API
Example fix
// before keymaps.registerKeymap(['n'], name, fn) // name === '' // after if (!name) return keymaps.registerKeymap(['n'], name, fn)
Defensive patterns
Strategy: validation
Validate before calling
const valid = typeof name === 'string' && name.length > 0
if (!valid) throw new TypeError('keymap name must be a non-empty string') Type guard
const isValidKeymapName = (n): n is string => typeof n === 'string' && n.length > 0
Try / catch
try {
keymaps.registerKeymap(['n'], name, handler)
} catch (e) {
if (String(e.message).startsWith('Invalid key')) logger.error(`bad keymap name: ${JSON.stringify(name)}`)
else throw e
} Prevention
- 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
When it happens
Trigger: Calling keymaps.registerKeymap(['n'], '', fn) or with a variable that is undefined due to a bad import/config.
Common situations: Extension keymap registration built from dynamic values that resolve to empty strings; copy-pasted registration code missing the name argument.
Related errors
- name and doComplete required for createSource
- Feature param could only starts with nvim and patch
- Command: ${command} not found
- keymap: "${name}" already exists.
- select kind "${kind}" not supported
AI-assisted analysis of neoclide/coc.nvim@50e974d969 (2026-08-31).
Data as JSON: /api/errors/138d7b542cef7021.
Report an issue: GitHub.