pcottle/learnGitBranching · error · GitError

git-error-options

Error message

git-error-options

What it means

Ref-validation guard in checkout/switch: after resolving the target and normalizing remote branches to their referenced commit, the target's type must be one of 'branch', 'tag', or 'commit'. Anything else (detached HEAD placeholder, blob/tree-like refs, or an internal ref object) is not checkoutable.

Source

Thrown at src/js/git/index.js:2680

  return mergeCommit;
};

GitEngine.prototype.checkout = function(idOrTarget) {
  var target = this.resolveID(idOrTarget);
  if (target.get('id') === 'HEAD') {
    // git checkout HEAD is a
    // meaningless command but i used to do this back in the day
    return;
  }

  var type = target.get('type');
  // check if this is an origin branch, and if so go to the commit referenced
  if (type === 'branch' && target.getIsRemote()) {
    target = this.getCommitFromRef(target.get('id'));
  }

  if (type !== 'branch' && type !== 'tag' && type !== 'commit') {
    throw new GitError({
      msg: intl.str('git-error-options')
    });
  }
  if (type === 'tag') {
    target = target.get('target');
  }

  this.HEAD.set('target', target);
};

GitEngine.prototype.forceBranch = function(branchName, where) {
  branchName = this.crappyUnescape(branchName);
  // if branchname doesn't exist...
  if (!this.doesRefExist(branchName)) {
    this.branch(branchName, where);
  }

  var branch = this.resolveID(branchName);

View on GitHub (pinned to 5b09d0ff96)

Solutions

  1. Pass a concrete branch name, tag name, or commit id to checkout
  2. Re-attach HEAD to a branch before further ref-based operations
  3. Inspect resolveID(target).attributes.type first and reject non-branch/tag/commit values

Example fix

// before
this.checkout('some-file.txt');
// after
this.checkout('main');
Defensive patterns

Strategy: type-guard

Validate before calling

var t = engine.resolveID(target);
var type = t && t.attributes ? t.attributes.type : undefined;
if (type !== 'branch' && type !== 'tag' && type !== 'commit') throw new Error('bad target');

Type guard

function isCheckoutable(engine, id) {
  var r = engine.resolveID(id);
  var t = r && r.attributes && r.attributes.type;
  return t === 'branch' || t === 'tag' || t === 'commit';
}

Prevention

When it happens

Trigger: Calling checkout with options.target resolving to a ref whose type attribute is not branch/tag/commit — e.g. checking out HEAD while it is detached in a state the engine considers invalid, or passing an arbitrary object/id that resolves to an unsupported ref type.

Common situations: Passing raw file names or malformed ids to checkout; engine-level code passing an unresolved wrapper object; levels that detach HEAD then attempt further operations with a stale handle.

Related errors


AI-assisted analysis of pcottle/learnGitBranching@5b09d0ff96 (2026-08-27). Data as JSON: /api/errors/042f5d10061ee718. Report an issue: GitHub.