{"record":{"id":"dfa8c35b51b34823","repo":"FreshRSS/FreshRSS","slug":"error-during-git-checkout-git-directory-does-not","errorCode":null,"errorMessage":"Error during git checkout: .git directory does not seem writable! Please git pull manually!","messagePattern":"Error during git checkout: \\.git directory does not seem writable! Please git pull manually!","errorType":"exception","errorClass":"Minz_Exception","httpStatus":null,"severity":"error","filePath":"app/Controllers/updateController.php","lineNumber":19,"sourceCode":"<?php\ndeclare(strict_types=1);\n\nclass FreshRSS_update_Controller extends FreshRSS_ActionController {\n\n\tprivate const LASTUPDATEFILE = 'last_update.txt';\n\n\tpublic static function isGit(): bool {\n\t\treturn is_dir(FRESHRSS_PATH . '/.git/');\n\t}\n\n\t/**\n\t * Automatic change to the new name of edge branch since FreshRSS 1.18.0,\n\t * and perform checks for several git errors.\n\t * @throws Minz_Exception\n\t */\n\tpublic static function migrateToGitEdge(): bool {\n\t\tif (!is_writable(FRESHRSS_PATH . '/.git/config')) {\n\t\t\tthrow new Minz_Exception('Error during git checkout: .git directory does not seem writable! ' .\n\t\t\t\t'Please git pull manually!');\n\t\t}\n\n\t\tif (!function_exists('exec')) {\n\t\t\tthrow new Minz_Exception('Error during git checkout: exec() function is disabled! ' .\n\t\t\t\t'Please git pull manually!');\n\t\t}\n\n\t\texec('git --version', $output, $return);\n\t\tif ($return != 0) {\n\t\t\tthrow new Minz_Exception(\"Error {$return} git not found: Please update manually!\");\n\t\t}\n\n\t\t//Note `git branch --show-current` requires git 2.22+\n\t\texec('git symbolic-ref --short HEAD 2>&1', $output, $return);\n\t\tif ($return != 0) {\n\t\t\tthrow new Minz_Exception(\"Error {$return} during git symbolic-ref: \" .\n\t\t\t\t'Reapply `chown www-data:www-data -R ' . FRESHRSS_PATH . '` ' .","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/FreshRSS/FreshRSS/blob/95842d81c1b8ab673389544f072559aeb8cd7591/app/Controllers/updateController.php#L1-L37","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Run chown -R www-data:www-data on the FreshRSS directory (as the message itself suggests) so .git/config is writable","If ownership cannot be changed, run git pull / git checkout edge manually as a user who can write, then reload","Verify open_basedir does not exclude FRESHRSS_PATH"],"exampleFix":"# before\nls -ld /var/www/FreshRSS/.git\tdrwx------ root root\n# after\nsudo chown -R www-data:www-data /var/www/FreshRSS\nsudo -u www-data test -w /var/www/FreshRSS/.git/config && echo ok","handlingStrategy":"validation","validationCode":"if (FreshRSS_update_Controller::isGit() && !is_writable(FRESHRSS_PATH . '/.git/config')) {\n\techo '.git not writable by PHP user - fix ownership before running the update';\n\treturn;\n}","typeGuard":null,"tryCatchPattern":"try {\n\tFreshRSS_update_Controller::migrateToGitEdge();\n} catch (Minz_Exception $e) {\n\t// surface the embedded manual instruction verbatim\n\techo $e->getMessage();\n}","preventionTips":["Clone git installs as the web-server user, or chown immediately after a root install","Run cli/access-permissions.sh after any CLI operation","Keep FRESHRSS_PATH inside open_basedir when it is configured"],"tags":["update","git","permissions","freshrss"],"backgroundTag":"file-permission-denied","analyzedSha":"95842d81c1b8ab673389544f072559aeb8cd7591","analyzedAt":"2026-08-23T00:21:00.265Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}