{"record":{"id":"348fa3c217ada1b6","repo":"phalcon/cphalcon","slug":"router-cache-is-corrupt-or-invalid-expected-array","errorCode":null,"errorMessage":"Router cache is corrupt or invalid (expected array, got {gettype}): {path}","messagePattern":"Router cache is corrupt or invalid \\(expected array, got (.+?)\\): (.+?)","errorType":"exception","errorClass":"Phalcon\\Mvc\\Router\\Exception","httpStatus":null,"severity":"error","filePath":"phalcon/Mvc/Router.zep","lineNumber":958,"sourceCode":"\n    /**\n     * File-shaped helper around loadDispatcherFromArray(). Includes the\n     * file (opcache-friendly) and forwards the return value.\n     *\n     * @throws \\Phalcon\\Mvc\\Router\\Exception\n     */\n    public function loadDispatcher( string path) -> void\n    {\n        var dump;\n\n        if !this->phpFileExists(path) {\n            throw new Exception(\"Router cache not found: \" . path);\n        }\n\n        let dump = require path;\n\n        if typeof dump !== \"array\" {\n            throw new Exception(\n                \"Router cache is corrupt or invalid (expected array, got \" . gettype(dump) . \"): \" . path\n            );\n        }\n\n        this->loadDispatcherFromArray(dump);\n    }\n\n    /**\n     * Cache-instance convenience wrapper. On cache hit, restores the\n     * dispatcher immediately. On miss, defers cache population until the\n     * next handle() completes - at which point buildDispatcherDump() is\n     * written to the cache key.\n     *\n     * @throws \\Phalcon\\Mvc\\Router\\Exception\n     */\n    public function useCache(<CacheAdapterInterface> cache,  string key = \"phalcon.router.dispatcher\") -> void\n    {\n        var stored;","sourceCodeStart":940,"sourceCodeEnd":976,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Mvc/Router.zep#L940-L976","documentation":"loadDispatcher() include/requires the cache file and expects it to return an array (files written by dumpDispatcher() start with '<?php return array(...);'). If require yields anything else - a scalar, null, or even PHP output captured as a non-array - the file is declared corrupt or invalid, with the actual gettype() included in the message.","triggerScenarios":"The cache file was hand-edited and no longer returns an array; a truncated/partially written file (crash before atomic rename, or someone edited in place); a file at that path that is plain PHP code executing side effects instead of returning data; output before the return statement turning the include result into echoed text; wrong file entirely (a config PHP file) sitting at the cache path.","commonSituations":"Manual 'fixes' to generated caches; deploy pipelines that copy files mid-write; code that points the loader at a hand-written bootstrap file; whitespace/BOM or debug statements injected above the return by tooling.","solutions":["Delete the corrupt file and regenerate it with dumpDispatcher()","Never hand-edit generated cache files; change route definitions and re-dump instead","Treat 'corrupt or invalid' as a cache-miss in a wrapper: catch Phalcon\\Mvc\\Router\\Exception, unlink the file, rebuild routes dynamically, re-dump","Verify with a quick check that require returns an array before handing it to the router (see validation pattern)"],"exampleFix":"// before\n$router->loadDispatcher($path); // file returns a scalar / executes code -> throws\n\n// after: self-healing load with regenerate-on-corruption\ntry {\n    $router->loadDispatcher($path);\n} catch (\\Phalcon\\Mvc\\Router\\Exception $e) {\n    @unlink($path);\n    buildRoutes($router)->dumpDispatcher($path);\n    $router->loadDispatcher($path);\n}","handlingStrategy":"try-catch","validationCode":"// Cheap pre-check when reusing a dump you did not just generate\n$dump = require $path;\nif (!is_array($dump)) {\n    unlink($path);\n    buildRoutes($router)->dumpDispatcher($path);\n    $dump = require $path;\n}\n$router->loadDispatcherFromArray($dump);","typeGuard":"function returnsArray(string $phpFile): bool\n{\n    $value = include $phpFile; // side-effect free for well-formed dumps\n    return is_array($value);\n}","tryCatchPattern":"try {\n    $router->loadDispatcher($path);\n} catch (\\Phalcon\\Mvc\\Router\\Exception $e) {\n    @unlink($path);                          // quarantined corrupt file\n    buildRoutes($router)->dumpDispatcher($path);\n    $router->loadDispatcher($path);\n}","preventionTips":["Never hand-edit generated cache files; change route definitions and re-dump","Keep the cache path exclusive to the dumper - no shared 'generated' files with other tools","Alert when the self-healing path fires more than once; that signals a writer bug or truncation"],"tags":["phalcon","router","caching","corruption"],"backgroundTag":"cache-corrupt","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}