BookStackApp/BookStack · error · ThemeModuleException
Module in folder "{$folderName}" is missing a valid 'name' p
Error message
Module in folder "{$folderName}" is missing a valid 'name' property What it means
ThemeModule::fromJson validates a module's JSON descriptor (module.php/meta file) and throws ThemeModuleException when the 'name' key is absent, empty, or not a string. The folder name is included in the message to identify the offending module.
Source
Thrown at app/Theming/ThemeModule.php:23
readonly class ThemeModule
{
public function __construct(
public string $name,
public string $description,
public string $version,
public string $folderName,
) {
}
/**
* Create a ThemeModule instance from JSON data.
*
* @throws ThemeModuleException
*/
public static function fromJson(array $data, string $folderName): self
{
if (empty($data['name']) || !is_string($data['name'])) {
throw new ThemeModuleException("Module in folder \"{$folderName}\" is missing a valid 'name' property");
}
if (!isset($data['description']) || !is_string($data['description'])) {
throw new ThemeModuleException("Module in folder \"{$folderName}\" is missing a valid 'description' property");
}
if (!isset($data['version']) || !is_string($data['version'])) {
throw new ThemeModuleException("Module in folder \"{$folderName}\" is missing a valid 'version' property");
}
if (!preg_match('/^v?\d+\.\d+\.\d+(-.*)?$/', $data['version'])) {
throw new ThemeModuleException("Module in folder \"{$folderName}\" has an invalid 'version' format. Expected semantic version format like '1.0.0' or 'v1.0.0'");
}
return new self(
name: $data['name'],
description: $data['description'],
version: $data['version'],View on GitHub (pinned to 18f8469a1c)
Solutions
- Open the module folder named in the message and add/fix the 'name' key as a non-empty string in its descriptor
- Verify you're editing the exact file BookStack parses (check ThemeModule loader conventions, e.g. module.php returning an array)
- Re-download/repackage the module from a trusted source if the file is corrupted
- Check for case-sensitivity typos in the JSON keys
Example fix
// before (module descriptor)
{ "description": "My module" }
// after
{ "name": "my-module", "description": "My module" } Defensive patterns
Strategy: validation
Validate before calling
function validateModuleDescriptor(array $data, string $folder): void {
if (empty($data['name']) || !is_string($data['name'])) {
throw new InvalidArgumentException("Module in folder \"{$folder}\" needs a non-empty string 'name'");
}
} Type guard
function hasValidName(array $data): bool {
return isset($data['name']) && is_string($data['name']) && $data['name'] !== '';
} Try / catch
try {
$module = ThemeModule::fromJson($data, $folderName);
} catch (ThemeModuleException $e) {
Log::warning('Invalid theme module', ['folder' => $folderName, 'error' => $e->getMessage()]);
// skip module or fail upload with clear message
} Prevention
- Include name, description, and version in every module descriptor
- Use lowercase kebab-case keys exactly as documented (JSON is case-sensitive)
- Lint descriptor JSON before packaging a module ZIP
- Test module loading locally before distributing
When it happens
Trigger: Loading theme modules via loadFromFolder or getModuleInstance where the module's JSON/file returns an array without a valid string 'name' property — e.g. missing key, null, or an empty string.
Common situations: Hand-written module.json files with a typo ('Name' instead of 'name'); modules copied from older themes predating the descriptor format; empty or corrupted descriptor files; packaging the wrong file so $data is empty.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Module in folder "{$folderName}" is missing a valid 'descrip
- Module in folder "{$folderName}" is missing a valid 'version
- Module in folder "{$folderName}" has an invalid 'version' fo
- Failed to load module from zip file after extraction
- Book to move chapter into not found
AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02).
Data as JSON: /api/errors/5eb1328467ff899f.
Report an issue: GitHub.