getgrav/grav · error · RuntimeException
Unknown extension type
Error message
Unknown extension type
What it means
AbstractFilesystemStorage::getFile() maps the configured data formatter's default file extension to a compiled file class and only accepts '.json', '.yaml' and '.md'; anything else throws 'Unknown extension type'. The flex storage configuration therefore declares a formatter whose extension is unsupported by this storage backend (note that '.yml' is NOT accepted, only '.yaml').
Source
Thrown at system/src/Grav/Framework/Flex/Storage/AbstractFilesystemStorage.php:170
}
return null;
}
/**
* @param string $filename
* @return CompiledJsonFile|CompiledYamlFile|CompiledMarkdownFile
*/
protected function getFile(string $filename)
{
$filename = $this->resolvePath($filename);
// TODO: start using the new file classes.
$file = match ($this->dataFormatter->getDefaultFileExtension()) {
'.json' => CompiledJsonFile::instance($filename),
'.yaml' => CompiledYamlFile::instance($filename),
'.md' => CompiledMarkdownFile::instance($filename),
default => throw new RuntimeException('Unknown extension type ' . $this->dataFormatter->getDefaultFileExtension()),
};
return $file;
}
/**
* @param string $path
* @return string
*/
protected function resolvePath(string $path): string
{
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
if (!$locator->isStream($path)) {
return GRAV_ROOT . "/{$path}";
}
View on GitHub (pinned to 6040efed04)
Solutions
- Set the formatter extension to one of the supported values: file_extension: json, yaml (not yml), or md.
- If you need another format, implement a storage subclass overriding getFile() to return your own compiled file class.
- Verify the option is actually reaching the formatter: check getDefaultFileExtension() on the configured formatter instance.
- Watch for whitespace/missing dot in the configured value.
Example fix
# before (flex blueprint)
storage:
class: Grav\Framework\Flex\Storage\FileStorage
options:
formatter:
class: Grav\Framework\File\Formatter\YamlFormatter
options:
file_extension: .yml
# after
storage:
class: Grav\Framework\Flex\Storage\FileStorage
options:
formatter:
class: Grav\Framework\File\Formatter\YamlFormatter
options:
file_extension: .yaml Defensive patterns
Strategy: validation
Validate before calling
// Validate the formatter/extension pair before the flex type is used
$ext = $formatter->getDefaultFileExtension();
if (!in_array($ext, ['.json', '.yaml', '.md'], true)) {
throw new \InvalidArgumentException(
"Flex file storage supports .json/.yaml/.md, got '{$ext}'"
);
} Prevention
- Use file_extension: .yaml — '.yml' is not accepted by this storage.
- Stick to the bundled JsonFormatter/YamlFormatter/MarkdownFormatter for file storage.
- For other formats, subclass the storage and override getFile() with your compiled-file class.
- Lint flex blueprints (storage.options.formatter) in CI.
When it happens
Trigger: A flex collection/blueprint configured with storage: options: formatter: {class: ..., options: {file_extension: yml|neon|csv|txt}}; a custom formatter subclass that returns a different getDefaultFileExtension(); typos like 'yaml ' with a space or missing leading dot.
Common situations: Copy-pasting a flex blueprint and changing the format to 'yml' out of habit (other systems prefer it); writing a custom formatter for a niche format without also subclassing the storage; blueprint YAML indentation putting file_extension under the wrong key so a default leaks through.
Related errors
- Bad Data Formatter
- Bad storage class: %s
- Invalid storage key: "%s"
- No backups defined...
- Backup location: {$backup_root} does not exist...
AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17).
Data as JSON: /api/errors/f384019f541326fd.
Report an issue: GitHub.