{"record":{"id":"9dcdde56ff6459aa","repo":"flarum/framework","slug":"custom-less","errorCode":null,"errorMessage":"custom_less","messagePattern":"custom_less","errorType":"validation","errorClass":"ValidationException","httpStatus":null,"severity":"error","filePath":"framework/core/src/Forum/ValidateCustomLess.php","lineNumber":106,"sourceCode":"                return new OverrideSettingsRepository($settings, $event->settings);\n            }\n        );\n\n        $assetsDir = $this->assets->getAssetsDir();\n\n        $adapter = new InMemoryFilesystemAdapter();\n        $this->assets->setAssetsDir(new FilesystemAdapter(new Filesystem($adapter), $adapter));\n\n        $this->settings->delete('custom_less_error');\n\n        try {\n            $this->assets->makeCss()->commit();\n\n            foreach ($this->locales->getLocales() as $locale => $name) {\n                $this->assets->makeLocaleCss($locale)->commit();\n            }\n        } catch (Less_Exception_Parser $e) {\n            throw new ValidationException(['custom_less' => $e->getMessage()]);\n        }\n\n        if (! empty($this->settings->get('custom_less_error'))) {\n            throw new ValidationException(['custom_less' => $this->settings->get('custom_less_error')]);\n        }\n\n        $this->assets->setAssetsDir($assetsDir);\n        $this->container->instance(SettingsRepositoryInterface::class, $settings);\n    }\n\n    public function whenSettingsSaved(Saved $event): void\n    {\n        if (! isset($event->settings['custom_less']) && ! $this->hasDirtyCustomLessSettings($event)) {\n            return;\n        }\n\n        // Flag rather than delete, so the stylesheets already referenced by\n        // served pages keep resolving until their replacements exist. The","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/flarum/framework/blob/4b939f685389bfe8a380e9e28ddf305a1c66950c/framework/core/src/Forum/ValidateCustomLess.php#L88-L124","documentation":"In ValidateCustomLess::whenSettingsSaving, after re-writing settings in a trial compile, the code builds CSS assets for the default and each locale. If less.php raises Less_Exception_Parser during compilation, it is re-thrown as ValidationException keyed on 'custom_less' with the parser's message — meaning the saved custom LESS contains syntax errors.","triggerScenarios":"Saving custom LESS that fails to compile: unbalanced braces, invalid LESS syntax, bad variable usage, or any construct the Less parser rejects while running makeCss()/makeLocaleCss() commits.","commonSituations":"Admins pasting SCSS (not LESS) into custom_less; copy/paste truncation leaving unclosed braces; LESS referencing undefined mixins/variables from a removed extension.","solutions":["Read the parser message shown in the admin panel — it includes the line/character of the syntax error — and fix the LESS at that location.","Validate balanced braces and LESS-compatible syntax (convert SCSS-specific syntax like $variables to LESS @variables).","Revert to the previously working custom LESS, then re-apply changes incrementally to find the offending snippet."],"exampleFix":"// before\n.button { color: $primary; }\n\n// after (LESS syntax, not SCSS)\n.button { color: @primary; }","handlingStrategy":"try-catch","validationCode":"// quick local check with less.php before saving\n$parser = new Less_Parser();\ntry { $parser->parse($customLess); } catch (Less_Exception_Parser $e) {\n  // show $e->getMessage() (has line/column) before submitting\n}","typeGuard":null,"tryCatchPattern":"try {\n    $this->settings->save(['custom_less' => $less]);\n} catch (ValidationException $e) {\n    $msg = $e->errors()['custom_less'] ?? 'Invalid LESS';\n}","preventionTips":["Compile LESS locally before pasting into the admin panel.","Use LESS syntax, not SCSS (@variables not $variables).","Apply big style changes incrementally so failures are easy to localize.","Check braces balance when copy/pasting long stylesheets."],"tags":["flarum","less","syntax-error","validation","custom-styles"],"backgroundTag":"schema-validation-failed","analyzedSha":"4b939f685389bfe8a380e9e28ddf305a1c66950c","analyzedAt":"2026-09-15T18:09:20.879Z","contentChangedAt":"2026-09-15T18:09:20.879Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}