{"record":{"id":"3f046d42d6fe74bc","repo":"octobercms/october","slug":"the-this-manifestpath-directory-must-be-presen","errorCode":null,"errorMessage":"The {$this->manifestPath} directory must be present and writable.","messagePattern":"The (.+?) directory must be present and writable\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"modules/system/classes/ManifestCache.php","lineNumber":154,"sourceCode":"            }\n        }\n\n        $this->manifest += $manifest;\n\n        $this->manifestLoaded = true;\n    }\n\n    /**\n     * write the given manifest array to disk\n     */\n    protected function write(array $manifest)\n    {\n        if (!$this->useManifest || $this->manifestPath === null) {\n            return;\n        }\n\n        if (!is_writable(dirname($this->manifestPath))) {\n            throw new Exception(\"The {$this->manifestPath} directory must be present and writable.\");\n        }\n\n        File::put(\n            $this->manifestPath,\n            '<?php return '.var_export($manifest, true).';'\n        );\n    }\n}\n","sourceCodeStart":136,"sourceCodeEnd":163,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/system/classes/ManifestCache.php#L136-L163","documentation":"ManifestCache persists the CMS manifest (registered plugins, modules, etc.) as a PHP array file at cache_path('cms/manifest.php') and writes it on shutdown after registrations. write() throws a plain Exception when dirname(manifestPath) — the framework cache directory, by default storage/framework/cache — is missing or not writable. Note useManifest is disabled in debug mode (useManifest = !System::checkDebugMode()), so this frequently surfaces only in production.","triggerScenarios":"Deploying to a fresh server where storage/framework/cache was never created; running php artisan optimize / cache:clear or any request that mutates the manifest as a user without write permission (root-owned files from a root deploy); moved/custom cache path that does not exist; open_basedir or SELinux blocking the directory.","commonSituations":"Post-deploy permission drift after uploading as root and serving as www-data; CI pipelines that run composer/artisan as a different user than the web server; containerized setups where the storage volume mount is read-only; local environments copied without the storage skeleton.","solutions":["Create the directory: mkdir -p storage/framework/cache.","Give the web/CLI user write access: chown -R www-data:www-data storage (or chmod -R ug+rwx storage as appropriate).","Run artisan and web requests as the same user to avoid root-owned cache files.","If cache_path was customized, verify the configured directory exists and is writable."],"exampleFix":"# before\n$ php artisan cache:clear\nException: The /app/storage/framework/cache/cms/manifest.php directory must be present and writable.\n\n# after\n$ mkdir -p storage/framework/cache\n$ chown -R www-data:www-data storage\n$ php artisan cache:clear","handlingStrategy":"validation","validationCode":"// Pre-flight in a deploy script or service provider boot\n$manifestDir = dirname(cache_path('cms/manifest.php'));\nif (!is_dir($manifestDir)) {\n    mkdir($manifestDir, 0775, true);\n}\nif (!is_writable($manifestDir)) {\n    throw new RuntimeException(\"Cache directory {$manifestDir} is not writable by \" . get_current_user());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run deploy/artisan commands as the web server user so cache files stay writable by both.","Include storage/framework/cache in deployment skeletons and volume mounts.","Add a health check that touches a file in the cache directory on each deploy."],"tags":["php","cache","permissions","filesystem","deployment"],"backgroundTag":"permission-denied","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}