BookStackApp/BookStack · error · ThemeModuleException
Module in folder "{$folderName}" has an invalid 'version' fo
Error message
Module in folder "{$folderName}" has an invalid 'version' format. Expected semantic version format like '1.0.0' or 'v1.0.0' What it means
ThemeModule::fromJson throws ThemeModuleException when 'version' is a string but does not match the semantic-version regex /^v?\d+\.\d+\.\d+(-.*)?$/ — it must look like '1.0.0' or 'v1.0.0', optionally with a pre-release suffix.
Source
Thrown at app/Theming/ThemeModule.php:35
*
* @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'],
folderName: $folderName,
);
}
/**
* Get a path for a file within this module.
*/
public function path($path = ''): string
{
$component = trim($path, '/');
return theme_path("modules/{$this->folderName}/{$component}");
}View on GitHub (pinned to 18f8469a1c)
Solutions
- Rewrite the version as MAJOR.MINOR.PATCH, e.g. '1.0.0'
- Optionally prefix with 'v' ('v1.0.0' is accepted)
- Put pre-release info after a hyphen, e.g. '1.0.0-beta.1'
- Remove extra components like a fourth number or trailing metadata that breaks the pattern
Example fix
// before "version": "1.0 beta" // after "version": "1.0.0-beta"
Defensive patterns
Strategy: validation
Validate before calling
function validateSemver(string $version): bool {
return preg_match('/^v?\d+\.\d+\.\d+(-.*)?$/', $version) === 1;
}
// run before packaging: if (!validateSemver($data['version'])) fail; Type guard
function isSemverString(mixed $v): bool {
return is_string($v) && preg_match('/^v?\d+\.\d+\.\d+(-.*)?$/', $v) === 1;
} Try / catch
try {
$module = ThemeModule::fromJson($data, $folderName);
} catch (ThemeModuleException $e) {
if (str_contains($e->getMessage(), "invalid 'version' format")) {
// prompt for MAJOR.MINOR.PATCH format
}
} Prevention
- Adopt strict semver (three numeric parts, optional leading 'v')
- Put pre-release tags after a hyphen: '1.0.0-beta.1'
- Validate versions with the same regex in release tooling
- Avoid informal tags like 'latest', 'dev', or two-part versions
When it happens
Trigger: Descriptor has a string 'version' such as '1.0', 'v1', '1.0.0.1', 'beta', or '1.0.0 beta' (space instead of hyphen) that fails the semver pattern.
Common situations: Two-part versions ('1.0'); informal tags ('latest', 'dev'); versions with spaces or build metadata in the wrong place; authors used to loose versioning from other platforms.
Related errors
- Module in folder "{$folderName}" is missing a valid 'version
- Module in folder "{$folderName}" is missing a valid 'name' p
- Module in folder "{$folderName}" is missing a valid 'descrip
- 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/b0883373dbd0a4fa.
Report an issue: GitHub.