{"record":{"id":"69e6a6bf520f1bfa","repo":"dianping/cat","slug":"mark-not-set","errorCode":null,"errorMessage":"Mark not set","messagePattern":"Mark not set","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cat-home/src/main/webapp/assets/js/editor/keybinding-vim.js","lineNumber":4341,"sourceCode":"\n        return result;\n      },\n      parseLineSpec_: function(cm, inputStream) {\n        var numberMatch = inputStream.match(/^(\\d+)/);\n        if (numberMatch) {\n          return parseInt(numberMatch[1], 10) - 1;\n        }\n        switch (inputStream.next()) {\n          case '.':\n            return cm.getCursor().line;\n          case '$':\n            return cm.lastLine();\n          case '\\'':\n            var mark = cm.state.vim.marks[inputStream.next()];\n            if (mark && mark.find()) {\n              return mark.find().line;\n            }\n            throw new Error('Mark not set');\n          default:\n            inputStream.backUp(1);\n            return undefined;\n        }\n      },\n      parseCommandArgs_: function(inputStream, params, command) {\n        if (inputStream.eol()) {\n          return;\n        }\n        params.argString = inputStream.match(/.*/)[0];\n        var delim = command.argDelimiter || /\\s+/;\n        var args = trim(params.argString).split(delim);\n        if (args.length && args[0]) {\n          params.args = args;\n        }\n      },\n      matchCommand_: function(commandName) {\n        for (var i = commandName.length; i > 0; i--) {","sourceCodeStart":4323,"sourceCodeEnd":4359,"githubUrl":"https://github.com/dianping/cat/blob/e815e74d4c2dd74edac831241f1253fcc7d25381/cat-home/src/main/webapp/assets/js/editor/keybinding-vim.js#L4323-L4359","documentation":"Thrown by the CodeMirror vim keybinding's line-address parser when an ex command uses a mark address (`'{mark}`, e.g. `:'a,'b d`) but the named mark is not set on the editor, or the mark's position can no longer be resolved via `mark.find()`. Marks are per-editor state stored in `cm.state.vim.marks`; a mark set in another editor instance, a cleared mark, or a mark whose text was deleted yields no findable position. The parser deliberately throws because it cannot translate the address into a line number.","triggerScenarios":"Running an ex command with a `'a` style address (e.g. `:'a,'bs/old/new/g`, `:'a d`) before ever setting mark `a` with `ma` in normal mode; using marks after the marked lines were deleted so `mark.find()` returns null; using a mark set in a different CodeMirror instance sharing the keymap; buffer operations that reset `cm.state.vim.marks`.","commonSituations":"Users typing vim-style range commands while exploring the vim emulation; automated test suites replaying ex commands against a fresh editor with no marks initialized; plugins that pipe `:'<,'>`-style ranges with a stale register; version upgrades of the vim keybinding where mark storage moved into `cm.state.vim.marks`.","solutions":["Set the mark first in normal mode (e.g. `ma` on the target line) before issuing `:'a,...` commands.","Use a mark-independent address instead: `.` for the cursor line (`:.,$d`) or `$` for the last line.","If scripting, verify the mark exists and is findable before dispatching the command (check `cm.state.vim.marks[name] && cm.state.vim.marks[name].find()`).","If the marked text was deleted, re-set the mark on a stable line and retry."],"exampleFix":"// before\ncm.openDialog(':a', (cmd) => cm.state.vim.handleEx(cm, cmd)); // ':a d' -> Error: Mark not set\n\n// after\n// in normal mode press: m a   (sets mark a)\n// then run:  :'a,'b d\nif (cm.state.vim && cm.state.vim.marks['a'] && cm.state.vim.marks['a'].find()) {\n  cm.state.vim.handleEx(cm, \"'a,'b d\");\n}","handlingStrategy":"validation","validationCode":"function markIsUsable(cm, name) {\n  var mark = cm.state.vim && cm.state.vim.marks && cm.state.vim.marks[name];\n  return !!(mark && typeof mark.find === 'function' && mark.find());\n}\n// before dispatching a command that uses a mark address:\nif (!markIsUsable(cm, 'a')) { /* set it or refuse */ CodeMirror.Vim.handleEx(cm, 'ma'); }","typeGuard":null,"tryCatchPattern":"try {\n  CodeMirror.Vim.handleEx(cm, \"'a,'b d\");\n} catch (e) {\n  if (/Mark not set/.test(e.message)) { showHint('Set mark first: m a'); return; }\n  throw e;\n}","preventionTips":["Always create marks (m{a}) in the same editor instance before using '{a} addresses.","Prefer '.' (cursor) and '$' (last line) addresses for scripted ranges — they never throw.","When automating ex commands, validate mark existence with markIsUsable() first.","Re-set marks after bulk edits that delete lines, since a mark on deleted text is unfindable."],"tags":["vim","codemirror","keybinding","marks","ex-command"],"backgroundTag":null,"analyzedSha":"e815e74d4c2dd74edac831241f1253fcc7d25381","analyzedAt":"2026-08-14T14:22:34.512Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}