dianping/cat · error · Error

Mark not set

Error message

Mark not set

What it means

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.

Source

Thrown at cat-home/src/main/webapp/assets/js/editor/keybinding-vim.js:4341

        return result;
      },
      parseLineSpec_: function(cm, inputStream) {
        var numberMatch = inputStream.match(/^(\d+)/);
        if (numberMatch) {
          return parseInt(numberMatch[1], 10) - 1;
        }
        switch (inputStream.next()) {
          case '.':
            return cm.getCursor().line;
          case '$':
            return cm.lastLine();
          case '\'':
            var mark = cm.state.vim.marks[inputStream.next()];
            if (mark && mark.find()) {
              return mark.find().line;
            }
            throw new Error('Mark not set');
          default:
            inputStream.backUp(1);
            return undefined;
        }
      },
      parseCommandArgs_: function(inputStream, params, command) {
        if (inputStream.eol()) {
          return;
        }
        params.argString = inputStream.match(/.*/)[0];
        var delim = command.argDelimiter || /\s+/;
        var args = trim(params.argString).split(delim);
        if (args.length && args[0]) {
          params.args = args;
        }
      },
      matchCommand_: function(commandName) {
        for (var i = commandName.length; i > 0; i--) {

View on GitHub (pinned to e815e74d4c)

Solutions

  1. Set the mark first in normal mode (e.g. `ma` on the target line) before issuing `:'a,...` commands.
  2. Use a mark-independent address instead: `.` for the cursor line (`:.,$d`) or `$` for the last line.
  3. 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()`).
  4. If the marked text was deleted, re-set the mark on a stable line and retry.

Example fix

// before
cm.openDialog(':a', (cmd) => cm.state.vim.handleEx(cm, cmd)); // ':a d' -> Error: Mark not set

// after
// in normal mode press: m a   (sets mark a)
// then run:  :'a,'b d
if (cm.state.vim && cm.state.vim.marks['a'] && cm.state.vim.marks['a'].find()) {
  cm.state.vim.handleEx(cm, "'a,'b d");
}
Defensive patterns

Strategy: validation

Validate before calling

function markIsUsable(cm, name) {
  var mark = cm.state.vim && cm.state.vim.marks && cm.state.vim.marks[name];
  return !!(mark && typeof mark.find === 'function' && mark.find());
}
// before dispatching a command that uses a mark address:
if (!markIsUsable(cm, 'a')) { /* set it or refuse */ CodeMirror.Vim.handleEx(cm, 'ma'); }

Try / catch

try {
  CodeMirror.Vim.handleEx(cm, "'a,'b d");
} catch (e) {
  if (/Mark not set/.test(e.message)) { showHint('Set mark first: m a'); return; }
  throw e;
}

Prevention

When it happens

Trigger: 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`.

Common situations: 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`.

Related errors


AI-assisted analysis of dianping/cat@e815e74d4c (2026-08-14). Data as JSON: /api/errors/69e6a6bf520f1bfa. Report an issue: GitHub.