{"record":{"id":"11bf265ebbfe4f96","repo":"octobercms/october","slug":"slug-must-not-be-empty","errorCode":null,"errorMessage":"Slug must not be empty","messagePattern":"Slug must not be empty","errorType":"exception","errorClass":"SystemException","httpStatus":null,"severity":"error","filePath":"modules/dashboard/models/Dashboard.php","lineNumber":139,"sourceCode":"        UserPreference::forUser()->set($this->getUserPreferencesKey($owner, $field), $definition);\n    }\n\n    /**\n     * resetDashboardPreference\n     */\n    public function resetDashboardPreference($owner, $field)\n    {\n        UserPreference::forUser()->reset($this->getUserPreferencesKey($owner, $field));\n    }\n\n    /**\n     * updateDashboard\n     */\n    public function updateDashboard($owner, $field, $definition)\n    {\n        $field = strtolower($field);\n        if (!strlen($field)) {\n            throw new SystemException('Slug must not be empty');\n        }\n\n        $dashboard = self::applyOwner($owner)->where('code', $field)->first();\n        if (!$dashboard) {\n            throw new ApplicationException(\n                __(\"Cannot find a dashboard with the specified slug: \\\":slug\\\".\", ['slug' => $field])\n            );\n        }\n\n        $dashboard->is_custom = true;\n        $dashboard->definition = $definition;\n        $dashboard->save();\n    }\n\n    /**\n     * scopeListDashboards\n     */\n    public function scopeListDashboards($query, $owner)","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/dashboard/models/Dashboard.php#L121-L157","documentation":"Dashboard::updateDashboard($owner, $field, $definition) lowercases the slug-like $field and throws SystemException('Slug must not be empty') when strlen($field) is 0 — i.e. the request tried to update a dashboard identified by an empty slug. Note the check happens after strtolower() and only catches truly empty strings: ' ' (whitespace) passes this guard and instead fails the subsequent lookup. The next step queries dashboards by code, so an empty slug means the caller never resolved which dashboard to update.","triggerScenarios":"An AJAX/API save-dashboard request where the 'slug' parameter is missing, null-coalesced to '' (e.g. post('slug', '')); front-end saving a newly created dashboard before assigning its code; route/controller forwarding an unset route parameter into updateDashboard.","commonSituations":"Dashboard creation flow sends the definition before the slug is generated; JS builds the request payload with a renamed key (code vs slug) so the back-end reads an empty value; a test calling updateDashboard($owner, '', $def) directly.","solutions":["Send the target dashboard's non-empty slug/code in the request payload using the key the controller reads (check the handler's post() key names).","In the create flow, generate/persist the slug first, then call updateDashboard with it.","In the controller, validate the request: if (!strlen($slug = trim(post('slug', '')))) return back()->withError(...); before touching the model.","Align front-end and back-end on one key name (slug vs code) to stop silent '' defaults."],"exampleFix":"// before\n$model->updateDashboard($owner, post('slug', ''), $definition);\n\n// after\n$slug = strtolower(trim((string) post('slug', '')));\nif ($slug === '') {\n    throw new ApplicationException('Dashboard slug is required.');\n}\n$model->updateDashboard($owner, $slug, $definition);","handlingStrategy":"validation","validationCode":"$slug = strtolower(trim((string) post('slug', '')));\nif ($slug === '') {\n    throw new ApplicationException('Dashboard slug is required.');\n}\n$model->updateDashboard($owner, $slug, $definition);","typeGuard":null,"tryCatchPattern":"try {\n    $model->updateDashboard($owner, $slug, $definition);\n} catch (SystemException $e) {\n    if (str_contains($e->getMessage(), 'Slug must not be empty')) {\n        return response()->json(['error' => 'Dashboard slug is required.'], 422);\n    }\n    throw $e;\n}","preventionTips":["Trim and validate the slug in the controller before calling updateDashboard.","Generate and persist the dashboard slug before allowing definition saves from the UI.","Keep the request payload key name (slug) in sync between front-end and back-end."],"tags":["dashboard","model-validation","slug","request-payload"],"backgroundTag":"missing-required-parameter","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}