FreshRSS/FreshRSS · error · Minz_Exception

Error during git checkout: .git directory does not seem writ

Error message

Error during git checkout: .git directory does not seem writable! Please git pull manually!

What it means

FreshRSS_update_Controller::migrateToGitEdge() (the one-time move from the old master/dev branch names to edge, introduced with 1.18.0) first checks is_writable(FRESHRSS_PATH . '/.git/config') and throws Minz_Exception when the git metadata is not writable by the PHP user. This is purely a filesystem ownership/permission problem; the automatic git update cannot proceed until fixed.

Source

Thrown at app/Controllers/updateController.php:19

<?php
declare(strict_types=1);

class FreshRSS_update_Controller extends FreshRSS_ActionController {

	private const LASTUPDATEFILE = 'last_update.txt';

	public static function isGit(): bool {
		return is_dir(FRESHRSS_PATH . '/.git/');
	}

	/**
	 * Automatic change to the new name of edge branch since FreshRSS 1.18.0,
	 * and perform checks for several git errors.
	 * @throws Minz_Exception
	 */
	public static function migrateToGitEdge(): bool {
		if (!is_writable(FRESHRSS_PATH . '/.git/config')) {
			throw new Minz_Exception('Error during git checkout: .git directory does not seem writable! ' .
				'Please git pull manually!');
		}

		if (!function_exists('exec')) {
			throw new Minz_Exception('Error during git checkout: exec() function is disabled! ' .
				'Please git pull manually!');
		}

		exec('git --version', $output, $return);
		if ($return != 0) {
			throw new Minz_Exception("Error {$return} git not found: Please update manually!");
		}

		//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 . '` ' .

View on GitHub (pinned to 95842d81c1)

Solutions

  1. Run chown -R www-data:www-data on the FreshRSS directory (as the message itself suggests) so .git/config is writable
  2. If ownership cannot be changed, run git pull / git checkout edge manually as a user who can write, then reload
  3. Verify open_basedir does not exclude FRESHRSS_PATH

Example fix

# before
ls -ld /var/www/FreshRSS/.git	drwx------ root root
# after
sudo chown -R www-data:www-data /var/www/FreshRSS
sudo -u www-data test -w /var/www/FreshRSS/.git/config && echo ok
Defensive patterns

Strategy: validation

Validate before calling

if (FreshRSS_update_Controller::isGit() && !is_writable(FRESHRSS_PATH . '/.git/config')) {
	echo '.git not writable by PHP user - fix ownership before running the update';
	return;
}

Try / catch

try {
	FreshRSS_update_Controller::migrateToGitEdge();
} catch (Minz_Exception $e) {
	// surface the embedded manual instruction verbatim
	echo $e->getMessage();
}

Prevention

When it happens

Trigger: Repo cloned as root while PHP runs as www-data; .git owned by root with restrictive modes; read-only mount; open_basedir excluding FRESHRSS_PATH.

Common situations: Manual git clone done under the root account and handed to the web server; Docker bind-mount with mismatched UID; hosting mounting the app read-only.

Related errors


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