getgrav/grav · error · InstallException
Could not update system configuration for Twig compatibility
Error message
Could not update system configuration for Twig compatibility settings
What it means
Postflight hook of a Grav 1.8.0 update: it defines Twig compatibility defaults in user/config/system.yaml only when the keys are absent (strict_mode.twig2_compat: false, strict_mode.twig3_compat: true among others) and saves via YamlUpdater. Any Exception during that read-modify-write is rethrown as InstallException 'Could not update system configuration for Twig compatibility settings', with the original exception chained for the real cause.
Source
Thrown at system/src/Grav/Installer/updates/1.8.0_2025-09-21_0.php:31
$yaml = YamlUpdater::instance(GRAV_ROOT . '/user/config/system.yaml');
if ($yaml->exists('strict_mode.twig_compat')) {
$value = $yaml->get('strict_mode.twig_compat');
$yaml->undefine('strict_mode.twig_compat');
$yaml->define('strict_mode.twig2_compat', $value);
}
if (!$yaml->exists('strict_mode.twig2_compat')) {
$yaml->define('strict_mode.twig2_compat', false);
}
if (!$yaml->exists('strict_mode.twig3_compat')) {
$yaml->define('strict_mode.twig3_compat', true);
}
$yaml->save();
} catch (\Exception $e) {
throw new InstallException('Could not update system configuration for Twig compatibility settings', $e);
}
}
];
View on GitHub (pinned to 6040efed04)
Solutions
- Make user/config/system.yaml writable by the account running direct-install and retry — the defines are guarded by exists() so re-running is safe
- Verify the file parses as valid YAML and fix/restore it if not
- Check the chained previous-exception message in the trace for the precise I/O error
Defensive patterns
Strategy: try-catch
Validate before calling
$file = GRAV_ROOT . '/user/config/system.yaml';
if (file_exists($file) && !is_writable($file)) {
throw new \RuntimeException("{$file} must be writable during the upgrade");
} Try / catch
try {
Install::instance()->run();
} catch (InstallException $e) {
if (str_contains($e->getMessage(), 'Twig compatibility settings')) {
// Config write failed post-file-copy; fix permissions and re-run direct-install
// (the define() calls are exists()-guarded, so the retry converges)
chmod(GRAV_ROOT . '/user/config/system.yaml', 0664);
}
} Prevention
- Ensure user/config ownership matches the upgrade user before running gpm
- Validate system.yaml parses cleanly prior to upgrading
- Re-running direct-install is safe — keys are only defined when absent
When it happens
Trigger: user/config/system.yaml unwritable by the upgrading user; the file containing YAML fragments the updater fails to parse; concurrent writes (another admin saving config mid-upgrade); disk full during save.
Common situations: Ownership mismatch between CLI upgrade user and web-server user; hand-edited or symlinked system.yaml; hosting with immutable config mounts.
Related errors
- Could not update system configuration to maintain backwards
- Could not remove the retired security.*.xss_scan_output sett
- Failed to update {file}: {message}
- Could not migrate the Twig-sandbox allowlists to the additiv
- Versions file cannot be read
AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17).
Data as JSON: /api/errors/ed5f75c88c626f47.
Report an issue: GitHub.