{"record":{"id":"314e93cd54dba74e","repo":"BookStackApp/BookStack","slug":"module-in-folder-foldername-is-missing-a-vali-314e93","errorCode":null,"errorMessage":"Module in folder \"{$folderName}\" is missing a valid 'version' property","messagePattern":"Module in folder \"(.+?)\" is missing a valid 'version' property","errorType":"exception","errorClass":"ThemeModuleException","httpStatus":null,"severity":"error","filePath":"app/Theming/ThemeModule.php","lineNumber":31,"sourceCode":"    }\n\n    /**\n     * Create a ThemeModule instance from JSON data.\n     *\n     * @throws ThemeModuleException\n     */\n    public static function fromJson(array $data, string $folderName): self\n    {\n        if (empty($data['name']) || !is_string($data['name'])) {\n            throw new ThemeModuleException(\"Module in folder \\\"{$folderName}\\\" is missing a valid 'name' property\");\n        }\n\n        if (!isset($data['description']) || !is_string($data['description'])) {\n            throw new ThemeModuleException(\"Module in folder \\\"{$folderName}\\\" is missing a valid 'description' property\");\n        }\n\n        if (!isset($data['version']) || !is_string($data['version'])) {\n            throw new ThemeModuleException(\"Module in folder \\\"{$folderName}\\\" is missing a valid 'version' property\");\n        }\n\n        if (!preg_match('/^v?\\d+\\.\\d+\\.\\d+(-.*)?$/', $data['version'])) {\n            throw new ThemeModuleException(\"Module in folder \\\"{$folderName}\\\" has an invalid 'version' format. Expected semantic version format like '1.0.0' or 'v1.0.0'\");\n        }\n\n        return new self(\n            name: $data['name'],\n            description: $data['description'],\n            version: $data['version'],\n            folderName: $folderName,\n        );\n    }\n\n    /**\n     * Get a path for a file within this module.\n     */\n    public function path($path = ''): string","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/BookStackApp/BookStack/blob/18f8469a1c72f8cc8497e9372635e6dea5028071/app/Theming/ThemeModule.php#L13-L49","documentation":"ThemeModuleException guard in ThemeModule::fromJson rejecting a bookstack-module.json manifest whose 'version' value is absent or not a string. Input at fault: the module's JSON manifest with an invalid version field.","triggerScenarios":"fromJson receives $data where 'name' and 'description' are valid but 'version' is absent, null, or a non-string value (e.g. a float like 1.0 written without quotes, which PHP decodes as a number).","commonSituations":"Authors writing \"version\": 1.0 (unquoted number) in JSON; descriptors copied from templates without a version; hand-edited files where the version line was deleted.","solutions":["Add a 'version' key as a quoted string, e.g. \"1.0.0\"","Quote numeric versions — unquoted JSON numbers fail the is_string check","Follow semantic version format to also pass the next validation (see error 126)","Bump the version string when republishing a fixed module"],"exampleFix":"// before\n{ \"version\": 1.0 }\n// after\n{ \"version\": \"1.0.0\" }","handlingStrategy":"validation","validationCode":"function validateVersionPresent(array $data, string $folder): void {\n    if (!isset($data['version']) || !is_string($data['version'])) {\n        throw new InvalidArgumentException(\"Module in folder \\\"{$folder}\\\" needs a string 'version'\");\n    }\n}","typeGuard":"function hasStringVersion(array $data): bool {\n    return isset($data['version']) && is_string($data['version']);\n}","tryCatchPattern":"try {\n    $module = ThemeModule::fromJson($data, $folderName);\n} catch (ThemeModuleException $e) {\n    if (str_contains($e->getMessage(), \"'version' property\")) {\n        // instruct author to add a quoted semver string\n    }\n}","preventionTips":["Always quote version values in JSON: \"version\": \"1.0.0\", never 1.0","Use a JSON schema validator on module descriptors before packaging","Keep versions as strings in any build tooling that generates descriptors","Review descriptors after automated edits/generators"],"tags":["theming","validation","json","semver","bookstack"],"backgroundTag":"missing-required-argument","analyzedSha":"18f8469a1c72f8cc8497e9372635e6dea5028071","analyzedAt":"2026-09-02T19:49:33.068Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}