openai/codex-plugin-cc · error · Error

Unable to detect the repository default branch. Pass --base

Error message

Unable to detect the repository default branch. Pass --base <ref> or use --scope working-tree.

What it means

Thrown by detectDefaultBranch() when it cannot determine the repository's default branch. It first tries `git symbolic-ref refs/remotes/origin/HEAD`, then probes a fixed list of candidate branch names (main, master, trunk) against both local refs and origin remotes; if none resolve, it gives up. This is a heuristic guess, not a guarantee — repos with non-standard branch names (develop, default, release) defeat it.

Source

Thrown at plugins/codex/scripts/lib/git.mjs:115

    const remoteHead = symbolic.stdout.trim();
    if (remoteHead.startsWith("refs/remotes/origin/")) {
      return remoteHead.replace("refs/remotes/origin/", "");
    }
  }

  const candidates = ["main", "master", "trunk"];
  for (const candidate of candidates) {
    const local = git(cwd, ["show-ref", "--verify", "--quiet", `refs/heads/${candidate}`]);
    if (local.status === 0) {
      return candidate;
    }
    const remote = git(cwd, ["show-ref", "--verify", "--quiet", `refs/remotes/origin/${candidate}`]);
    if (remote.status === 0) {
      return `origin/${candidate}`;
    }
  }

  throw new Error("Unable to detect the repository default branch. Pass --base <ref> or use --scope working-tree.");
}

export function getCurrentBranch(cwd) {
  return gitChecked(cwd, ["branch", "--show-current"]).stdout.trim() || "HEAD";
}

export function getWorkingTreeState(cwd) {
  const staged = gitChecked(cwd, ["diff", "--cached", "--name-only"]).stdout.trim().split("\n").filter(Boolean);
  const unstaged = gitChecked(cwd, ["diff", "--name-only"]).stdout.trim().split("\n").filter(Boolean);
  const untracked = gitChecked(cwd, ["ls-files", "--others", "--exclude-standard"]).stdout.trim().split("\n").filter(Boolean);

  return {
    staged,
    unstaged,
    untracked,
    isDirty: staged.length > 0 || unstaged.length > 0 || untracked.length > 0
  };
}

View on GitHub (pinned to db52e28f4d)

Solutions

  1. Pass an explicit base ref: invoke the review with --base <ref> (e.g. --base origin/develop).
  2. Run the review in working-tree scope: use --scope working-tree to skip branch detection entirely.
  3. Make a candidate branch detectable: `git remote set-head origin -a` so symbolic-ref resolves, or rename/create a main|master|trunk branch.
  4. If your default branch is non-standard, set origin/HEAD: `git remote set-head origin <your-default-branch>`.

Example fix

// before
resolveReviewTarget(cwd, { scope: "branch" });

// after
resolveReviewTarget(cwd, { scope: "branch", base: "origin/develop" });
Defensive patterns

Strategy: validation

Validate before calling

import { execFileSync } from "node:child_process";

function hasDetectableDefaultBranch(cwd) {
  // origin/HEAD set?
  try {
    execFileSync("git", ["-C", cwd, "symbolic-ref", "refs/remotes/origin/HEAD"], { stdio: "ignore" });
    return true;
  } catch {}
  for (const c of ["main", "master", "trunk"]) {
    for (const ref of [`refs/heads/${c}`, `refs/remotes/origin/${c}`]) {
      try {
        execFileSync("git", ["-C", cwd, "show-ref", "--verify", "--quiet", ref], { stdio: "ignore" });
        return true;
      } catch {}
    }
  }
  return false;
}

// before calling resolveReviewTarget in branch/auto mode:
const opts = hasDetectableDefaultBranch(cwd)
  ? { scope: "branch" }
  : { scope: "working-tree" }; // or { base: "origin/develop" }

Try / catch

try {
  resolveReviewTarget(cwd, { scope: "branch" });
} catch (err) {
  if (/Unable to detect the repository default branch/.test(err.message)) {
    // fall back to an explicit base or working-tree scope
    resolveReviewTarget(cwd, { scope: "working-tree" });
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: Calling resolveReviewTarget(cwd, {scope:'branch'}) (or scope 'auto' with a clean tree) on a repo where origin/HEAD is unset AND no local or remote branch named main/master/trunk exists. Triggered by the codex review command in branch/auto mode when --base is not supplied.

Common situations: Freshly cloned repo where `git remote set-head` was never run; a repo whose default branch is named `develop` or `release/*`; a bare or detached-HEAD checkout; CI environments that shallow-clone without origin/HEAD metadata; a local-only repo with no remote configured.

Related errors


AI-assisted analysis of openai/codex-plugin-cc@db52e28f4d (2026-08-13). Data as JSON: /api/errors/753960e2599c6a8e. Report an issue: GitHub.