Leantime/leantime · warning · RuntimeException
Plugin %s is already enabled
Error message
Plugin %s is already enabled
What it means
This browser console.warn fires on the program-board variant of the ticket kanban (app/Domain/Tickets/Templates/showKanban.blade.php:393). When $programBoard is true, the template builds ticketStatusList from $allKanbanColumns and hands control to `leantime.pgmProBoard.initProgramKanban(...)`, which lives in the commercial PgmPro plugin's JS bundle. The guard `if (leantime.pgmProBoard && typeof leantime.pgmProBoard.initProgramKanban === 'function')` fails when that bundle was never loaded — app/Plugins is a private git submodule that is essentially empty in the OSS repo — so drag-and-drop and per-project status persistence are disabled while the board still renders read-only-ish.
Source
Thrown at app/Command/EnablePluginCommand.php:42
protected function configure(): void
{
$this->addArgument('plugin', InputArgument::REQUIRED, 'The plugin name');
}
/**
* {@inheritdoc}
*/
protected function executeCommand(): int
{
$name = $this->input->getArgument('plugin');
$plugin = $this->getPlugin($name);
if (! isset($plugin->id)) {
throw new RuntimeException(sprintf('Plugin %s is not installed', $plugin->name));
}
if ($plugin->enabled) {
throw new RuntimeException(sprintf('Plugin %s is already enabled', $plugin->name));
}
if (! $this->confirm(sprintf('Enable plugin %s', $plugin->name))) {
return Command::SUCCESS;
}
return $this->plugins->enablePlugin($plugin->id) ? Command::SUCCESS : Command::FAILURE;
}
}
View on GitHub (pinned to 9a9f49f100)
Solutions
- Verify the plugin is installed and enabled: `php bin/leantime plugin:list` then `php bin/leantime plugin:enable <pgmpro-plugin-name>` (install from marketplace with `plugin:install` and a valid license key if missing).
- If you have the private plugin repo access, initialize/update the submodule so plugin JS actually exists: `git submodule update --init --recursive` and rebuild plugin assets (`npx mix` inside the plugin).
- Open the browser Network tab on the kanban page and confirm the PgmPro script returns 200 and not 403/404; fix the plugin's asset path or rebuild public/dist if it 404s.
- Check the browser console and Leantime storage/logs for an earlier JS/PHP error that prevented the plugin bootstrapping, and for license-validation failures that auto-disabled the plugin.
- If the program board is intentionally unavailable in your edition, stop routing users to it (hide the program-board menu entry) so the degraded state is never presented.
Example fix
// before — hard dependency, silent degradation when plugin absent
if (leantime.pgmProBoard && typeof leantime.pgmProBoard.initProgramKanban === 'function') {
leantime.pgmProBoard.initProgramKanban(ticketStatusList);
} else {
console.warn('PgmPro board JS is not loaded; program kanban drag-and-drop is disabled.');
}
// after — make the degraded state visible to the user, not just the console
if (leantime.pgmProBoard && typeof leantime.pgmProBoard.initProgramKanban === 'function') {
leantime.pgmProBoard.initProgramKanban(ticketStatusList);
} else {
console.warn('[Tickets] PgmPro board JS is not loaded; program kanban drag-and-drop is disabled.');
jQuery.growl({ message: 'Drag & drop requires the PgmPro plugin, which is not active.' , style: 'warning' });
jQuery('.tknCard').addClass('no-drag'); // make read-only affordance explicit
} Defensive patterns
Strategy: type-guard
Validate before calling
// Server-side: before rendering the program board, verify the plugin that provides pgmProBoard is actually enabled
$pluginEnabled = app(\Leantime\Domain\Plugins\Services\Plugins::class)
->getEnabledPlugins()
->contains(fn ($p) => str_contains($p->name, 'PgmPro'));
// Only pass programBoard=true to the template when $pluginEnabled — otherwise render the regular board Type guard
// Feature-detect the plugin controller before wiring program-board drag-and-drop
function programBoardAvailable() {
return typeof window.leantime === 'object'
&& window.leantime !== null
&& typeof window.leantime.pgmProBoard === 'object'
&& typeof window.leantime.pgmProBoard.initProgramKanban === 'function';
}
if (programBoardAvailable()) {
leantime.pgmProBoard.initProgramKanban(ticketStatusList);
} else {
console.warn('[Tickets] PgmPro board JS is not loaded; program kanban drag-and-drop is disabled.');
notifyUser('Drag & drop requires the PgmPro plugin.');
} Prevention
- Gate the program-board route/menu on plugin status server-side so users never reach the degraded view.
- After `plugin:enable` or a submodule update, hard-reload and check the Network tab for a 200 on the plugin script before QA-signing the board.
- Monitor for license-triggered plugin auto-disable (user count over limit) — it removes the JS without touching your templates.
- Keep the feature detection (typeof checks) in any code path that depends on optional-plugin controllers.
When it happens
Trigger: Opening a program kanban board (/tickets/showKanban with the program board context) when: (1) the PgmPro plugin is not installed, not enabled (`plugin:enable pgmpro`), or its license check disabled it (Leantime disables plugins when the user count exceeds the license); (2) the plugin's compiled JS failed to load (404 on its assets because the submodule was not initialized after clone: `git submodule update --init`); (3) an earlier JS error aborted the bundle before it attached leantime.pgmProBoard to the global namespace; (4) a CSP or script-blocking extension prevented the plugin script from executing.
Common situations: OSS checkout where app/Plugins is the empty submodule and someone deep-links or restores a program-board URL; after a `system:update` or plugin license expiry that silently disabled PgmPro; staging copies missing the private submodule credentials; ad-blockers stripping the plugin's script tag on the kanban page.
Related errors
AI-assisted analysis of Leantime/leantime@9a9f49f100 (2026-08-21).
Data as JSON: /api/errors/d6b48d3bdf303950.
Report an issue: GitHub.