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

  1. 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
  2. Verify the file parses as valid YAML and fix/restore it if not
  3. 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

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


AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17). Data as JSON: /api/errors/ed5f75c88c626f47. Report an issue: GitHub.