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

  1. Set the formatter extension to one of the supported values: file_extension: json, yaml (not yml), or md.
  2. If you need another format, implement a storage subclass overriding getFile() to return your own compiled file class.
  3. Verify the option is actually reaching the formatter: check getDefaultFileExtension() on the configured formatter instance.
  4. 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

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


AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17). Data as JSON: /api/errors/f384019f541326fd. Report an issue: GitHub.