octobercms/october · error · SystemException
Slug must not be empty
Error message
Slug must not be empty
What it means
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.
Source
Thrown at modules/dashboard/models/Dashboard.php:139
UserPreference::forUser()->set($this->getUserPreferencesKey($owner, $field), $definition);
}
/**
* resetDashboardPreference
*/
public function resetDashboardPreference($owner, $field)
{
UserPreference::forUser()->reset($this->getUserPreferencesKey($owner, $field));
}
/**
* updateDashboard
*/
public function updateDashboard($owner, $field, $definition)
{
$field = strtolower($field);
if (!strlen($field)) {
throw new SystemException('Slug must not be empty');
}
$dashboard = self::applyOwner($owner)->where('code', $field)->first();
if (!$dashboard) {
throw new ApplicationException(
__("Cannot find a dashboard with the specified slug: \":slug\".", ['slug' => $field])
);
}
$dashboard->is_custom = true;
$dashboard->definition = $definition;
$dashboard->save();
}
/**
* scopeListDashboards
*/
public function scopeListDashboards($query, $owner)View on GitHub (pinned to b608633a7e)
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.
Example fix
// before
$model->updateDashboard($owner, post('slug', ''), $definition);
// after
$slug = strtolower(trim((string) post('slug', '')));
if ($slug === '') {
throw new ApplicationException('Dashboard slug is required.');
}
$model->updateDashboard($owner, $slug, $definition); Defensive patterns
Strategy: validation
Validate before calling
$slug = strtolower(trim((string) post('slug', '')));
if ($slug === '') {
throw new ApplicationException('Dashboard slug is required.');
}
$model->updateDashboard($owner, $slug, $definition); Try / catch
try {
$model->updateDashboard($owner, $slug, $definition);
} catch (SystemException $e) {
if (str_contains($e->getMessage(), 'Slug must not be empty')) {
return response()->json(['error' => 'Dashboard slug is required.'], 422);
}
throw $e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.
Related errors
- Cannot find a dashboard with the specified slug: ":slug".
- Custom widget class [{$widgetClass}] is not set.
- The property name is not specified.
- Custom widget class [{$widgetClass}] is not set.
- Trying to get selected row without a popup reference.
AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21).
Data as JSON: /api/errors/11bf265ebbfe4f96.
Report an issue: GitHub.