{"record":{"id":"1ea635cdea73d7ea","repo":"getgrav/grav","slug":"could-not-update-system-configuration-to-maintain","errorCode":null,"errorMessage":"Could not update system configuration to maintain backwards compatibility","messagePattern":"Could not update system configuration to maintain backwards compatibility","errorType":"exception","errorClass":"InstallException","httpStatus":null,"severity":"error","filePath":"system/src/Grav/Installer/updates/1.7.0_2020-11-20_1.php","lineNumber":21,"sourceCode":"use Grav\\Installer\\InstallException;\nuse Grav\\Installer\\VersionUpdate;\nuse Grav\\Installer\\YamlUpdater;\n\nreturn [\n    'preflight' => null,\n    'postflight' =>\n        function () {\n            /** @var VersionUpdate $this */\n            try {\n                // Keep old defaults for backwards compatibility.\n                $yaml = YamlUpdater::instance(GRAV_ROOT . '/user/config/system.yaml');\n                $yaml->define('twig.autoescape', false);\n                $yaml->define('strict_mode.yaml_compat', true);\n                $yaml->define('strict_mode.twig2_compat', true);\n                $yaml->define('strict_mode.blueprint_compat', true);\n                $yaml->save();\n            } catch (\\Exception $e) {\n                throw new InstallException('Could not update system configuration to maintain backwards compatibility', $e);\n            }\n        }\n];\n","sourceCodeStart":3,"sourceCodeEnd":25,"githubUrl":"https://github.com/getgrav/grav/blob/6040efed04efa69b8209448ed81308e7c24147c2/system/src/Grav/Installer/updates/1.7.0_2020-11-20_1.php#L3-L25","documentation":"This is the postflight hook of the Grav 1.7.0 schema update. It uses YamlUpdater to write backward-compatibility defaults into user/config/system.yaml (twig.autoescape: false, three strict_mode.* flags) and saves; any Exception from that write is rethrown as InstallException 'Could not update system configuration to maintain backwards compatibility'. The core files have already been installed at this point — only the user config mutation failed.","triggerScenarios":"user/config/system.yaml (or the user/config directory) being read-only or owned by another user when direct-install runs as CLI user; the file containing YAML the updater cannot parse/merge; disk full; file locked by a concurrent edit.","commonSituations":"CLI upgrade run as root while the file is owned by www-data (or vice versa); restored backups with wrong ownership; system.yaml hand-edited into invalid YAML before upgrading.","solutions":["Fix ownership/permissions so the user running direct-install can write user/config/system.yaml (e.g. `chown -R www-data:user user/config`)","Validate the file first: `bin/grav yamllint user/config/system.yaml` or re-parse it with a YAML linter, and restore from backup if broken","Free disk space / release locks, then re-run direct-install — the updater is idempotent"],"exampleFix":"# before\nsudo php bin/gpm direct-install tmp/grav-update.zip # root writes, file owned by www-data mode 644 -> write fails\n\n# after\nsudo -u www-data php bin/gpm direct-install tmp/grav-update.zip # run as the owning user","handlingStrategy":"try-catch","validationCode":"// Pre-flight: config must be writable and parseable before upgrading\n$file = GRAV_ROOT . '/user/config/system.yaml';\nif (file_exists($file)) {\n    if (!is_writable($file)) {\n        throw new \\RuntimeException(\"{$file} is not writable by \" . get_current_user());\n    }\n    try {\n        \\Symfony\\Component\\Yaml\\Yaml::parseFile($file);\n    } catch (\\Throwable $e) {\n        throw new \\RuntimeException(\"{$file} is not valid YAML: \" . $e->getMessage());\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    Install::instance()->run();\n} catch (InstallException $e) {\n    $prev = $e->getPrevious(); // the original YamlUpdater/IO failure\n    fwrite(STDERR, $e->getMessage() . ': ' . ($prev ? $prev->getMessage() : 'unknown'));\n    // Fix permissions/ownership, then re-run — the update hooks are idempotent\n}","preventionTips":["Run direct-install as the user that owns user/config (e.g. sudo -u www-data)","Lint user/config/system.yaml before every upgrade","Keep disk headroom and avoid concurrent admin saves during upgrades","Read the chained previous exception — it carries the real I/O or parse error"],"tags":["installer","yaml","configuration","filesystem-permissions","upgrade"],"backgroundTag":"config-file-write-failed","analyzedSha":"6040efed04efa69b8209448ed81308e7c24147c2","analyzedAt":"2026-08-17T05:07:31.593Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}