can1357/oh-my-pi · error · ToolError

branch ${localBranch} has no PR push metadata; check it out

Error message

branch ${localBranch} has no PR push metadata; check it out via op: pr_checkout first

What it means

resolvePrBranchPushTarget reads push metadata that op pr_checkout writes into git config under branch.<localBranch>.ompPrHeadRef (plus pushRemote/ompPrUrl/ompPrIsCrossRepository). If the ompPrHeadRef key is absent, the branch was not created by the PR checkout flow, so the tool refuses to guess where to push. This guards against pushing a plain local branch to the wrong remote/ref.

Source

Thrown at packages/coding-agent/src/tools/gh-pr-checkout.ts:230

	remoteName: string;
	remoteBranch: string;
	remoteUrl?: string;
	prUrl?: string;
	maintainerCanModify?: boolean;
	isCrossRepository: boolean;
}> {
	const repository = vcs.requireGit(repoRoot);
	const configPrefix = `branch.${localBranch}.`;
	const [headRef, pushRemote, remote, prUrl, maintainerCanModifyValue, isCrossRepositoryValue] = await Promise.all([
		repository.configGet(`${configPrefix}ompPrHeadRef`, signal),
		repository.configGet(`${configPrefix}pushRemote`, signal),
		repository.configGet(`${configPrefix}remote`, signal),
		repository.configGet(`${configPrefix}ompPrUrl`, signal),
		repository.configGet(`${configPrefix}ompPrMaintainerCanModify`, signal),
		repository.configGet(`${configPrefix}ompPrIsCrossRepository`, signal),
	]);
	if (!headRef) {
		throw new ToolError(`branch ${localBranch} has no PR push metadata; check it out via op: pr_checkout first`);
	}

	const remoteName = pushRemote ?? remote;
	if (!remoteName) {
		throw new ToolError(`branch ${localBranch} has no configured push remote`);
	}

	return {
		remoteName,
		remoteBranch: headRef,
		remoteUrl: (await repository.remoteUrl(remoteName, signal)) ?? undefined,
		prUrl: prUrl ?? undefined,
		maintainerCanModify:
			maintainerCanModifyValue == null
				? undefined
				: ["1", "true", "yes", "on"].includes(maintainerCanModifyValue.toLowerCase()),
		isCrossRepository: ["1", "true", "yes", "on"].includes((isCrossRepositoryValue ?? "").toLowerCase()),
	};

View on GitHub (pinned to 9690622007)

Solutions

  1. Check out the PR through the tool first: run `op pr_checkout <PR-number>` so it writes the push metadata, then retry the push.
  2. Alternatively set the metadata manually: `git config branch.<name>.ompPrHeadRef <head-branch-name>` (and branch.<name>.pushRemote / ompPrUrl as needed) before pushing.
  3. If you just want a normal push, use plain `git push -u <remote> <branch>` instead of the PR push flow.

Example fix

// before: pr_push on hand-made branch fails
// after: seed the metadata the tool expects
git config branch.my-fix.ompPrHeadRef my-fix
git config branch.my-fix.pushRemote origin
op pr_push --branch my-fix
Defensive patterns

Strategy: validation

Validate before calling

const headRef = await repo.configGet(`branch.${branch}.ompPrHeadRef`);
if (!headRef) throw new Error(`${branch} was not checked out via op pr_checkout — run pr_checkout first`);

Try / catch

try {
  await op.prPush({ branch });
} catch (err) {
  if (err instanceof ToolError && err.message.includes("no PR push metadata")) {
    await op.prCheckout({ prRef: prNumber, force: true }); // regenerate metadata, then retry
    await op.prPush({ branch });
  } else throw err;
}

Prevention

When it happens

Trigger: Running `op pr_push` (or any call to target/resolvePrBranchPushTarget) on a local branch that was created by hand or via plain `git checkout -b` / `git checkout` of a PR ref, rather than via `op pr_checkout`. Also occurs if someone ran `git config --unset branch.<name>.ompPrHeadRef` or wiped .git/config.

Common situations: Developer manually created a branch expecting pr_push to work; branch was checked out in a fresh clone where local config was not copied; config was cleaned by a script or `git config --local --remove-section`.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/8935eb7d434cddc0. Report an issue: GitHub.