Leantime/leantime · error · Leantime\Core\Exceptions\AuthorizationException
-32001
-32001
Error message
You are not allowed to re-sort tasks.
What it means
Tickets::sortTickets() (Gantt/kanban drag-drop re-sorting) first checks the SESSION-wide role with Auth::userIsAtLeast(Roles::$editor); anyone below editor (commenter, viewer) gets AuthorizationException (JSON-RPC -32001) regardless of project membership. Note the distinction: this first gate looks at the user's global session role, while the subsequent per-ticket loop checks project-scoped access — a user can pass this gate and still fail the later assignment check.
Source
Thrown at app/Domain/Tickets/Services/Tickets.php:3443
/**
* Authorized JSON-RPC entry point for Gantt re-sorting of tickets/milestones.
*
* Enforces editor+ and per-ticket project access (the RPC endpoint has no
* controller-level gate), then delegates to the internal updateTicketSorting().
*
* @param array $params Array of ticketId => sortPosition from Gantt drag-drop
* @return bool True on success (false only if the underlying write fails)
*
* @throws AuthorizationException If the caller is not an editor, or is not assigned to a referenced task's project
* @throws NotFoundException If a referenced task does not exist
*
* @api
*/
#[RequiresPermission(TicketsPermissions::EDIT, entityScoped: true)]
public function sortTickets(array $params): bool
{
if (! Auth::userIsAtLeast(Roles::$editor)) {
throw new AuthorizationException('You are not allowed to re-sort tasks.');
}
$userId = session('userdata.id');
foreach (array_keys($params) as $ticketId) {
$ticket = $this->getTicket((int) $ticketId);
if (! $ticket) {
throw new NotFoundException('A task referenced in the sort order could not be found.');
}
if (! $this->projectService->isUserAssignedToProject($userId, $ticket->projectId)) {
throw new AuthorizationException('You are not allowed to re-sort this task.');
}
}
return $this->updateTicketSorting($params);
}
/**
* Update ticket sorting with hierarchical cascade for milestone childrenView on GitHub (pinned to 9a9f49f100)
Solutions
- Perform sort calls with an editor+ (or higher) account
- Raise the user's role if they legitimately need to re-sort tasks
- Hide/disable drag-drop re-sorting for non-editor roles in the UI, and catch AuthorizationException (-32001) to show a clear message
Example fix
// before
$ticketsService->sortTickets($params); // fails for commenter role
// after
if (! \Leantime\Domain\Auth\Services\Auth::userIsAtLeast(\Leantime\Domain\Auth\Models\Roles::$editor)) {
return 'Sorting requires an editor role';
}
$ticketsService->sortTickets($params); Defensive patterns
Strategy: validation
Validate before calling
use Leantime\Domain\Auth\Models\Roles;
use Leantime\Domain\Auth\Services\Auth;
if (! Auth::userIsAtLeast(Roles::$editor)) {
return ['error' => 'Sorting tasks requires the editor role'];
}
$ok = $ticketsService->sortTickets($params); Try / catch
try {
$ok = $ticketsService->sortTickets($params);
} catch (\Leantime\Core\Exceptions\AuthorizationException $e) {
// -32001: session role below editor — disable drag-drop for this user
$ui->disableSorting();
} Prevention
- Enable drag-drop sorting only for editor+ users
- Check the session role with Auth::userIsAtLeast(Roles::$editor) before issuing sort calls
- Remember this gate is on the GLOBAL session role — re-login after role changes
When it happens
Trigger: A commenter or viewer account dragging tasks to re-sort; an API key whose underlying service-account user has a low role; a session carrying a stale role after the user's role was downgraded (session data predates the change).
Common situations: Drag-drop sort enabled in the UI for all roles; automations using a commenter-level API key; role downgrades that only take effect after re-login because the session still carries the old role.
Related errors
AI-assisted analysis of Leantime/leantime@9a9f49f100 (2026-08-21).
Data as JSON: /api/errors/b909921fdcb04417.
Report an issue: GitHub.