phalcon/cphalcon · error · CannotOpenCompiledFile
Extends compilation file {path} could not be opened
Error message
Extends compilation file {path} could not be opened What it means
Thrown in extends mode when Volt re-reads an already-compiled template (which must contain a serialized array of blocks) and file_get_contents() returns false. In extends mode Volt stores block definitions serialized in the compiled file; when that file exists (or stat check skipped) but cannot actually be read, the unserialization step is impossible and Volt aborts.
Source
Thrown at phalcon/Mvc/View/Engine/Volt/Compiler.zep:497
* Compare modification timestamps to check if the file
* needs to be recompiled
*/
if compare_mtime(templatePath, compiledTemplatePath) {
let compilation = this->compileFile(
templatePath,
compiledTemplatePath,
extendsMode
);
} else {
if extendsMode {
/**
* In extends mode we read the file that must
* contains a serialized array of blocks
*/
let blocksCode = this->phpFileGetContents(compiledTemplatePath);
if unlikely blocksCode === false {
throw new CannotOpenCompiledFile(compiledTemplatePath);
}
/**
* Unserialize the array blocks code
*/
if blocksCode {
let compilation = unserialize(blocksCode);
} else {
let compilation = [];
}
}
}
}
}
let this->compiledTemplatePath = compiledTemplatePath;
return compilation;View on GitHub (pinned to b7419de9cd)
Solutions
- Check read permissions on the compiled file and directory for the web server user (ls -l + ps aux | grep php)
- Clear the whole compiled Volt directory so templates regenerate atomically: rm -rf storage/cache/volt/*
- If open_basedir is enabled, ensure the compiled path is inside an allowed base dir
- Schedule cache clears during low traffic or use atomic directory swaps (build new dir, rename) to avoid read/write races
Example fix
// before cache/volt/ dir owned by root, app runs as www-data → read fails // after chown -R www-data:www-data storage/cache/volt chmod -R ug+rwX storage/cache/volt
Defensive patterns
Strategy: try-catch
Validate before calling
$compiledFile = $volt->getCompiler()->getCompiledTemplatePath($template); // or compute as configured
if ($compiledFile && !is_readable($compiledFile)) {
// regenerate before render
$volt->getCompiler()->compile($template);
} Try / catch
try {
echo $volt->render('page.volt', $params);
} catch (\Phalcon\Mvc\View\Engine\Volt\Exception $e) {
if (str_contains($e->getMessage(), 'could not be opened')) {
// cache file unreadable: purge and retry once
array_map('unlink', glob($cacheDir . '/*.php'));
echo $volt->render('page.volt', $params);
} else {
throw $e;
}
} Prevention
- Keep the compiled cache owned by the PHP-FPM user
- Clear the Volt cache with atomic directory swaps, never per-file unlinks during traffic
- Ensure open_basedir includes the compiled directory
When it happens
Trigger: An {% extends %} template is rendered, the compiled file exists at compiledTemplatePath, but the process cannot read it: wrong permissions, file removed between the exists-check and the read (race with cache clearing/deployment), or an open_basedir restriction that hides the path.
Common situations: Deployments that clear/regenerate the Volt cache while requests are in flight, compiled-cache directories written by root/CLI then read by the web server user, or open_basedir directives that cover the template dir but not the compiled dir.
Related errors
- Annotations directory cannot be written
- Stream adapter cannot read file: {path}
- Failed to write router cache temp file: {tmpPath}
- Failed to commit router cache: {path}
- View '{viewPath}' was not found in any of the views director
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/4133d0f3b7cbec64.
Report an issue: GitHub.