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

  1. 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).
  2. 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).
  3. 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.
  4. 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.
  5. 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

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.