FreshRSS/FreshRSS · error · Minz_Exception

Error {$return} during git checkout to edge branch! ' . 'Ple

Error message

Error {$return} during git checkout to edge branch! ' . 'Please change branch manually!

What it means

The actual branch switch, exec('git checkout edge --guess -f'), returned non-zero. --guess derives the local 'edge' branch from a remote tracking branch; common failure causes: no remote 'edge' ref exists (old clone never fetched since the rename), a stale .git/index.lock from a crashed or concurrent git process, untracked files that even -f refuses to clobber, or the same dubious-ownership refusal as the other git steps.

Source

Thrown at app/Controllers/updateController.php:50

		//Note `git branch --show-current` requires git 2.22+
		exec('git symbolic-ref --short HEAD 2>&1', $output, $return);
		if ($return != 0) {
			throw new Minz_Exception("Error {$return} during git symbolic-ref: " .
				'Reapply `chown www-data:www-data -R ' . FRESHRSS_PATH . '` ' .
				'or git pull manually! ' .
				json_encode($output, JSON_UNESCAPED_SLASHES));
		}
		$line = implode('', $output);
		if ($line !== 'master' && $line !== 'dev') {
			return true;	// not on master or dev, nothing to do
		}

		Minz_Log::warning('Automatic migration to git edge branch');
		unset($output);
		exec('git checkout edge --guess -f', $output, $return);
		if ($return != 0) {
			throw new Minz_Exception("Error {$return} during git checkout to edge branch! ' .
				'Please change branch manually!");
		}

		unset($output);
		exec('git reset --hard FETCH_HEAD', $output, $return);
		if ($return != 0) {
			throw new Minz_Exception("Error {$return} during git reset! Please git pull manually!");
		}

		return true;
	}

	public static function getCurrentGitBranch(): string {
		$output = [];
		exec('git branch --show-current', $output, $return);
		if ($return === 0) {
			return 'git branch: ' . $output[0];
		} else {

View on GitHub (pinned to 95842d81c1)

Solutions

  1. As the web user run: git fetch origin && git checkout edge --guess -f
  2. Remove a stale .git/index.lock when no git process is running
  3. Commit, stash or clean local modifications if the checkout reports conflicts
  4. Fix ownership/safe.directory as in the symbolic-ref error, then retry

Example fix

# before - auto checkout fails
sudo -u www-data git -C /var/www/FreshRSS checkout edge --guess -f
error: pathspec 'edge' did not match any file(s)
# after
sudo -u www-data git -C /var/www/FreshRSS fetch origin
sudo -u www-data git -C /var/www/FreshRSS checkout edge --guess -f
Defensive patterns

Strategy: try-catch

Validate before calling

exec('git -C ' . escapeshellarg(FRESHRSS_PATH) . ' fetch origin 2>&1', $o, $rc);
exec('git -C ' . escapeshellarg(FRESHRSS_PATH) . ' rev-parse --verify origin/edge 2>&1', $o2, $rc2);
if ($rc !== 0 || $rc2 !== 0) {
	echo 'origin/edge not available after fetch - resolve before migrating';
	return;
}

Try / catch

try {
	FreshRSS_update_Controller::migrateToGitEdge();
} catch (Minz_Exception $e) {
	// checkout step failed: fetch origin, clear index.lock, then retry or switch manually
	Minz_Log::error($e->getMessage());
}

Prevention

When it happens

Trigger: Clone predating the edge branch with no git fetch performed; a concurrent cron and web update racing on .git/index.lock; local modifications or untracked files conflicting with the checkout; safe.directory rejection.

Common situations: Long-lived git installs crossing the 1.18.0 branch rename; two update triggers firing simultaneously.

Related errors


AI-assisted analysis of FreshRSS/FreshRSS@95842d81c1 (2026-08-23). Data as JSON: /api/errors/c7aff7081612e6e6. Report an issue: GitHub.