can1357/oh-my-pi · error · ToolError

branch ${localBranch} has no configured push remote

Error message

branch ${localBranch} has no configured push remote

What it means

After finding ompPrHeadRef (2431), resolvePrBranchPushTarget computes the push remote as pushRemote ?? remote from branch.<localBranch>.* config. If neither key exists there is no remote to push to, so it throws. The checkout flow normally records one; this means the metadata is partially present but incomplete.

Source

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

	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()),
	};
}

export function formatPrCheckoutResult(options: {
	data: GhPrViewData;
	localBranch: string;

View on GitHub (pinned to 9690622007)

Solutions

  1. Set the push remote manually: `git config branch.<name>.pushRemote <remote>` (use the fork remote name, e.g. `upstream-pr-123` created by pr_checkout, or `origin` for same-repo PRs), then retry.
  2. Re-run `op pr_checkout <PR>` with force=true to regenerate the complete metadata set for the branch.
  3. For same-repo PRs, `git config branch.<name>.remote origin` is sufficient if pushRemote is absent.

Example fix

// before: pr_push fails with 'no configured push remote'
// after:
git config branch.my-fix.pushRemote origin
op pr_push --branch my-fix
Defensive patterns

Strategy: validation

Validate before calling

const pushRemote = await repo.configGet(`branch.${branch}.pushRemote`);
const remote = await repo.configGet(`branch.${branch}.remote`);
if (!pushRemote && !remote) {
  await repo.configSet(`branch.${branch}.pushRemote`, "origin"); // seed before calling the tool
}

Try / catch

try {
  await op.prPush({ branch });
} catch (err) {
  if (err instanceof ToolError && err.message.includes("no configured push remote")) {
    await git.config(["branch", branch, "pushRemote", "origin"]);
    await op.prPush({ branch });
  } else throw err;
}

Prevention

When it happens

Trigger: branch.<localBranch>.ompPrHeadRef exists but both branch.<localBranch>.pushRemote and branch.<localBranch>.remote are unset — e.g. metadata was hand-seeded with only the head ref, or a checkout from an older tool version wrote fewer keys, or a config section was partially edited/removed.

Common situations: Manually restoring config after a botched edit; copying branches between clones without the full config section; older checkout tool versions that predate writing pushRemote.

Related errors


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