ajaxorg/ace · error · Error

Mark not set

Error message

Mark not set

What it means

In vim ex command line specs, a mark reference ('x) looks up a previously set mark via getMarkPos. If the named mark was never set (or was invalidated), the position lookup returns null and the parser throws 'Mark not set', mirroring Vim's own behavior.

Source

Thrown at src/keyboard/vim.js:6128

        return result;
      },
      parseLineSpec_: function(cm, inputStream) {
        var numberMatch = inputStream.match(/^(\d+)/);
        if (numberMatch) {
          // Absolute line number plus offset (N+M or N-M) is probably a typo,
          // not something the user actually wanted. (NB: vim does allow this.)
          return parseInt(numberMatch[1], 10) - 1;
        }
        switch (inputStream.next()) {
          case '.':
            return this.parseLineSpecOffset_(inputStream, cm.getCursor().line);
          case '$':
            return this.parseLineSpecOffset_(inputStream, cm.lastLine());
          case '\'':
            var markName = inputStream.next();
            var markPos = getMarkPos(cm, cm.state.vim, markName);
            if (!markPos) throw new Error('Mark not set');
            return this.parseLineSpecOffset_(inputStream, markPos.line);
          case '-':
          case '+':
            inputStream.backUp(1);
            // Offset is relative to current line if not otherwise specified.
            return this.parseLineSpecOffset_(inputStream, cm.getCursor().line);
          default:
            inputStream.backUp(1);
            return undefined;
        }
      },
      parseLineSpecOffset_: function(inputStream, line) {
        var offsetMatch = inputStream.match(/^([+-])?(\d+)/);
        if (offsetMatch) {
          var offset = parseInt(offsetMatch[2], 10);
          if (offsetMatch[1] == "-") {
            line -= offset;
          } else {

View on GitHub (pinned to 2c1eddc392)

Solutions

  1. Set the mark first in normal mode (e.g. ma for mark a)
  2. Use a different line spec (%, ., $) that doesn't rely on marks
  3. Guard the command execution with a check that the mark exists

Example fix

// before
:’a,’b s/foo/bar/g  // marks never set -> throws
// after
:normal ma  // set mark a first
:'a,'b s/foo/bar/g
Defensive patterns

Strategy: validation

Validate before calling

// Ensure marks exist before running mark-based ranges
var marksSet = ['a', 'b'].every(function(m) {
  return !!window.__getMark && !!window.__getMark(m); // or track marks in your macro runner
});
if (!marksSet) return; // skip command or set marks first

Type guard

function markExists(cm, name) { try { return !!cm.ace.session; } catch (e) { return false; } } // verify via editor state before mark-based ranges

Try / catch

try { executeEx(":'a,'b s/x/y/g"); } catch (e) { if (/Mark not set/.test(e.message)) { /* set marks or use % range */ } else throw e; }

Prevention

When it happens

Trigger: Executing an ex range/command using a mark like :'a,'y s/x/y/ when mark 'a' was never set with ma; marks cleared by edits that deleted the marked line.

Common situations: Recording macros or remaps that assume marks exist; running commands on a freshly opened buffer where marks are unset.

Related errors


AI-assisted analysis of ajaxorg/ace@2c1eddc392 (2026-08-30). Data as JSON: /api/errors/ccb87ed95fcd2b96. Report an issue: GitHub.