{"record":{"id":"f0578a4284f77055","repo":"octobercms/october","slug":"invalid-handler-name","errorCode":null,"errorMessage":"Invalid handler name","messagePattern":"Invalid handler name","errorType":"exception","errorClass":"SystemException","httpStatus":null,"severity":"error","filePath":"modules/dashboard/classes/VueReportWidgetBase.php","lineNumber":69,"sourceCode":"     * @return void\n     */\n    public function bindToController()\n    {\n        $this->controller->registerVueComponent($this::class);\n    }\n\n    /**\n     * getData\n     */\n    abstract public function getData(ReportFetchData $data): mixed;\n\n    /**\n     * runHandler\n     */\n    public function runHandler(array $widgetConfig, string $handlerName, array $extraData): mixed\n    {\n        if (!preg_match('/^on[a-z0-9_]+/i', $handlerName)) {\n            throw new SystemException('Invalid handler name');\n        }\n\n        if (!method_exists($this, $handlerName)) {\n            throw new SystemException('Handler does not exist');\n        }\n\n        return $this->{$handlerName}($widgetConfig, $extraData);\n    }\n}\n","sourceCodeStart":51,"sourceCodeEnd":79,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/dashboard/classes/VueReportWidgetBase.php#L51-L79","documentation":"VueReportWidgetBase::runHandler() dispatches AJAX-style handlers by name and first enforces the October/Winter handler naming convention: the method name must match /^on[a-z0-9_]+/i — i.e. start with 'on' followed by at least one alphanumeric/underscore character. Anything else throws SystemException('Invalid handler name'). This mirrors the CMS AJAX handler convention (onSave, onLoadData) and blocks calling arbitrary PHP methods via the handler channel.","triggerScenarios":"A dashboard AJAX request invoking handler 'save', 'handle', 'on', 'on-submit' (hyphen), '__construct', or 'myOnLoad' — anything not literally starting with 'on'+word chars; front-end building the handler name dynamically and producing an empty/odd string; request payload key like 'on' alone which fails the regex because the character class needs at least one char after 'on'.","commonSituations":"Front-end dev names the method without the 'on' prefix; hyphenated or namespaced handler strings sent from JS; attempts to invoke lifecycle or inherited methods through the widget's AJAX endpoint (the guard blocks it).","solutions":["Name the widget handler method with the on prefix, e.g. public function onLoadDetails(array $widgetConfig, array $extraData), and invoke handler 'onLoadDetails'.","Fix the JS side to send exactly the PHP method name (camelCase, no hyphens/spaces, not just 'on').","If the handler legitimately needs a non-on name, add a thin public onXxx() wrapper that calls it rather than weakening the pattern.","Check for leading/trailing whitespace or encoding artifacts in the handler string from the request."],"exampleFix":"// before\npublic function loadDetails(array $widgetConfig, array $extraData) {}\n// JS sends handler: 'loadDetails'\n\n// after\npublic function onLoadDetails(array $widgetConfig, array $extraData) {}\n// JS sends handler: 'onLoadDetails'","handlingStrategy":"validation","validationCode":"$handler = (string) $request->input('handler', '');\nif (!preg_match('/^on[a-z0-9_]+$/i', $handler)) {\n    throw new ApplicationException('Invalid AJAX handler name.');\n}\n$widget->runHandler($config, $handler, $extra);","typeGuard":"function isValidHandlerName(string $name): bool\n{\n    return (bool) preg_match('/^on[a-z0-9_]+$/i', $name);\n}","tryCatchPattern":null,"preventionTips":["Adopt the on* naming convention for every AJAX handler from day one.","Send handler names from JS exactly as the PHP methods are named (camelCase, no separators).","Reject malformed handler names at the controller boundary with a 4xx, not a 500."],"tags":["dashboard","vue-report-widget","ajax-handler","naming-convention"],"backgroundTag":"invalid-handler-name","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}