{"record":{"id":"4936decc63fff45d","repo":"getgrav/grav","slug":"setup-configuration-reload-loop-detected","errorCode":null,"errorMessage":"Setup: Configuration reload loop detected!","messagePattern":"Setup: Configuration reload loop detected!","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"critical","filePath":"system/src/Grav/Common/Config/Setup.php","lineNumber":325,"sourceCode":"            $this->initializeLocator($locator);\n            $files = $locator->findResources('config://streams.yaml');\n\n            if ($check === $files) {\n                break;\n            }\n\n            // Update streams.\n            foreach (array_reverse($files) as $path) {\n                $file = CompiledYamlFile::instance($path);\n                $content = (array)$file->content();\n                if (!empty($content['schemes'])) {\n                    $this->items['streams']['schemes'] = $content['schemes'] + $this->items['streams']['schemes'];\n                }\n            }\n        } while (--$guard);\n\n        if (!$guard) {\n            throw new RuntimeException('Setup: Configuration reload loop detected!');\n        }\n\n        // Make sure we have valid setup.\n        $this->check($locator);\n\n        return $this;\n    }\n\n    /**\n     * Initialize resource locator by using the configuration.\n     *\n     * @param UniformResourceLocator $locator\n     * @return void\n     * @throws BadMethodCallException\n     */\n    public function initializeLocator(UniformResourceLocator $locator)\n    {\n        $locator->reset();","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/getgrav/grav/blob/6040efed04efa69b8209448ed81308e7c24147c2/system/src/Grav/Common/Config/Setup.php#L307-L343","documentation":"During Setup::init(), Grav repeatedly re-initializes the resource locator and re-scans config://streams.yaml, expecting the discovered file list to stabilize (the loop breaks when two consecutive lookups return the same $files). A $guard counter of 5 iterations prevents infinite recursion: if the streams.yaml lookup keeps yielding a different result every time — typically because stream definitions keep changing how config:// itself resolves — the guard runs out and RuntimeException 'Setup: Configuration reload loop detected!' is thrown. It indicates a cyclic or self-referential stream configuration.","triggerScenarios":"A user/config/streams.yaml (or one discovered via the config stream) that redefines the config scheme so each pass resolves config://streams.yaml to a different file set (e.g. chaining config:// to another directory that contains its own streams.yaml which redefines config again); environments or plugins layering contradictory stream prefixes; a stream path that only exists after another stream is initialized, so the list keeps growing.","commonSituations":"Hand-edited streams.yaml with self-referential config scheme overrides; a plugin or skeleton shipping a streams.yaml that conflicts with the site's; multi-environment setups (user/env/<host>/config/streams.yaml) creating alternating resolution orders; corrupted cache://compiled setup state left from an interrupted run.","solutions":["Inspect every streams.yaml that participates in the config stream (user/config/streams.yaml, user/env/*/config/streams.yaml, plugin-supplied ones) and remove any scheme redefinition that references config:// or chains back into it","Restore the stock stream definitions: diff your streams.yaml against system/defaults and keep only additive, non-cyclic overrides","Delete the compiled setup cache (cache/ directory) so init() starts from a clean slate","Disable recently added plugins one by one to find which one introduces the cyclic stream definition"],"exampleFix":"# user/config/streams.yaml — before (cyclic: redefines config:// pulling in another streams.yaml)\nstreams:\n  schemes:\n    config:\n      type: ReadOnlyStream\n      prefixes:\n        '': ['environment://config', 'user://config', 'system://config', 'user://extra-config']\n\n# after — drop the override entirely; the built-in defaults are already correct\n# (delete the file, or keep only non-config scheme overrides)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    $setup->init();\n} catch (RuntimeException $e) {\n    if (str_contains($e->getMessage(), 'reload loop')) {\n        // cyclic streams.yaml — fail fast with an ops alert instead of a white page\n        http_response_code(503);\n        error_log('Grav setup loop: check config://streams.yaml for cyclic scheme overrides');\n    }\n    throw $e;\n}","preventionTips":["Never redefine the config scheme inside streams.yaml in a way that adds new directories containing further streams.yaml files","Review plugin-supplied streams.yaml files before enabling new plugins in multi-environment setups","Clear cache/ after any stream-configuration change so init() rebuilds deterministically"],"tags":["grav","configuration","streams","infinite-loop","bootstrap"],"backgroundTag":"cyclic-configuration-loop","analyzedSha":"6040efed04efa69b8209448ed81308e7c24147c2","analyzedAt":"2026-08-17T05:07:31.593Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}