{"record":{"id":"621f2c238443cf43","repo":"ajaxorg/ace","slug":"vim-defineex-prefix-is-not-a-prefix-of","errorCode":null,"errorMessage":"(Vim.defineEx) \"'+prefix+'\" is not a prefix of \"'+name+'\", command not registered","messagePattern":"\\(Vim\\.defineEx\\) \"'\\+prefix\\+'\" is not a prefix of \"'\\+name\\+'\", command not registered","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/keyboard/vim.js","lineNumber":1675,"sourceCode":"                  }\n                }\n              }\n            }\n          }\n        }\n      },\n      langmap: updateLangmap,\n      vimKeyFromEvent: vimKeyFromEvent,\n      // TODO: Expose setOption and getOption as instance methods. Need to decide how to namespace\n      // them, or somehow make them work with the existing CodeMirror setOption/getOption API.\n      setOption: setOption,\n      getOption: getOption,\n      defineOption: defineOption,\n      defineEx: function(name, prefix, func){\n        if (!prefix) {\n          prefix = name;\n        } else if (name.indexOf(prefix) !== 0) {\n          throw new Error('(Vim.defineEx) \"'+prefix+'\" is not a prefix of \"'+name+'\", command not registered');\n        }\n        exCommands[name]=func;\n        exCommandDispatcher.commandMap_[prefix]={name:name, shortName:prefix, type:'api'};\n      },\n      handleKey: function (cm, key, origin) {\n        var command = this.findKey(cm, key, origin);\n        if (typeof command === 'function') {\n          return command();\n        }\n      },\n      multiSelectHandleKey: multiSelectHandleKey,\n\n      /**\n       * This is the outermost function called by CodeMirror, after keys have\n       * been mapped to their Vim equivalents.\n       *\n       * Finds a command based on the key (and cached keys if there is a\n       * multi-key sequence). Returns `undefined` if no key is matched, a noop","sourceCodeStart":1657,"sourceCodeEnd":1693,"githubUrl":"https://github.com/ajaxorg/ace/blob/2c1eddc392eb92cf222a4478f1893d2b2c354fb0/src/keyboard/vim.js#L1657-L1693","documentation":"Vim.defineEx(name, prefix, func) requires prefix to be a prefix of the command name (or omitted). Registering an ex command whose prefix isn't actually a prefix of the name would create an inconsistent command map, so it throws without registering.","triggerScenarios":"CodeMirror.defineEx('wq', 'w!', fn) or defineEx('substitute', 's', fn) where the prefix string isn't a leading substring of name.","commonSituations":"Custom ex command registration with abbreviated names that don't match; copy-pasted defineEx calls where name was edited but prefix wasn't.","solutions":["Make prefix an actual prefix of name, or pass null/undefined prefix to use the full name as prefix","Fix the name/prefix pair so name.indexOf(prefix) === 0","Remove the prefix argument if no abbreviation is needed"],"exampleFix":"// before\nVim.defineEx('writeall', 'wa!', fn); // 'wa!' not a prefix\n// after\nVim.defineEx('writeall', 'wa', fn);","handlingStrategy":"validation","validationCode":"function safeDefineEx(Vim, name, prefix, func) {\n  if (prefix && name.indexOf(prefix) !== 0) throw new Error('prefix must start name');\n  Vim.defineEx(name, prefix, func);\n}","typeGuard":"function isValidExPair(name, prefix) { return !prefix || name.indexOf(prefix) === 0; }","tryCatchPattern":"try { Vim.defineEx(name, prefix, fn); } catch (e) { if (/is not a prefix of/.test(e.message)) Vim.defineEx(name, null, fn); else throw e; }","preventionTips":["Omit the prefix argument unless you intentionally abbreviate","Ensure prefix is a leading substring of name","Unit-test custom ex command registrations"],"tags":["vim","api-misuse"],"backgroundTag":"invalid-command-prefix","analyzedSha":"2c1eddc392eb92cf222a4478f1893d2b2c354fb0","analyzedAt":"2026-08-30T00:39:52.222Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}