{"record":{"id":"8052c94d25e1d2fe","repo":"flarum/framework","slug":"cannot-modify-immutable-default-setting-key","errorCode":null,"errorMessage":"Cannot modify immutable default setting $key.","messagePattern":"Cannot modify immutable default setting \\$key\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"framework/core/src/Extend/Settings.php","lineNumber":117,"sourceCode":"    /**\n     * Register a setting that should trigger JS cache clear when saved.\n     *\n     * @param string $setting: The key of the setting.\n     */\n    public function resetJsCacheFor(string $setting): self\n    {\n        $this->resetJsCacheFor[] = $setting;\n\n        return $this;\n    }\n\n    public function extend(Container $container, ?Extension $extension = null): void\n    {\n        if (! empty($this->defaults)) {\n            $container->extend('flarum.settings.default', function (Collection $defaults) {\n                foreach ($this->defaults as $key => $value) {\n                    if ($defaults->has($key)) {\n                        throw new \\RuntimeException(\"Cannot modify immutable default setting $key.\");\n                    }\n\n                    $defaults->put($key, $value);\n                }\n\n                return $defaults;\n            });\n        }\n\n        if (! empty($this->resetWhen)) {\n            foreach ($this->resetWhen as $key => $callback) {\n                Arr::set(\n                    SetSettingsController::$resetWhen,\n                    $key,\n                    ContainerUtil::wrapCallback($callback, $container)\n                );\n            }\n        }","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/flarum/framework/blob/4b939f685389bfe8a380e9e28ddf305a1c66950c/framework/core/src/Extend/Settings.php#L99-L135","documentation":"Flarum's Extend\\Settings::extend() merges extension-provided default settings into the container's flarum.settings.default collection. If an extension tries to set a default for a key that already has a default (from core or another extension), it throws this RuntimeException, because defaults are immutable — extensions may only add new default keys, not override existing ones.","triggerScenarios":"An extension calling (new Extend\\Settings())->default('existing_key', $value) where 'existing_key' was already defaulted by Flarum core or a previously-loaded extension, executed during the container extend phase of boot.","commonSituations":"Two extensions both defining a default for the same setting key; an extension trying to override a core default to change behavior; upgrading Flarum where a key that used to be unclaimed now has a core default, breaking a previously working extension.","solutions":["Change the extension to use a unique settings key (prefixed with the extension id) instead of reusing the existing one.","Remove the ->default() call for keys owned by core/other extensions; read the existing value at runtime instead of trying to override it.","If overriding is truly needed, do it after boot by writing the setting to the DB (settings table) rather than via the defaults container extension.","Identify the conflicting extension by checking which other extension registers the same default key."],"exampleFix":"// before\n(new Extend\\Settings())->default('flarum-tags.min_primary_tags', 1)\n// after\n(new Extend\\Settings())->default('my-extension.min_primary_tags', 1) // unique, non-conflicting key","handlingStrategy":"validation","validationCode":"// ensure your default keys are namespaced and not core keys\nforeach ($myDefaults as $key => $value) {\n    if (str_starts_with($key, 'flarum-') && ! str_starts_with($key, 'flarum-my-extension-')) {\n        throw new \\LogicException(\"Do not override core default: $key\");\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    (new Extend\\Settings())->default($key, $value)->extend($container, $extension);\n} catch (\\RuntimeException $e) {\n    // log conflicting key and skip or rename it\n}","preventionTips":["Prefix all extension setting keys with your extension identifier.","Never call ->default() for keys already owned by core or other extensions.","Grep the codebase for the key before adding a new default.","Override behavior via DB settings (admin UI / Settings::set) rather than defaults."],"tags":["settings","extension","conflict","immutable-defaults"],"backgroundTag":"conflicting-config-options","analyzedSha":"4b939f685389bfe8a380e9e28ddf305a1c66950c","analyzedAt":"2026-09-15T18:09:20.879Z","contentChangedAt":"2026-09-15T18:09:20.879Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}