jackwener/OpenCLI · error · PluginError

Sub-plugin "${subPlugin}" is disabled in the manifest.

Error message

Sub-plugin "${subPlugin}" is disabled in the manifest.

What it means

When installing a specific sub-plugin from a monorepo, opencli filters the enabled plugins from the manifest. If the filter yields nothing, it distinguishes two cases: the sub-plugin exists in the manifest but is disabled, which produces this error. It tells you the name is correct but the manifest has it turned off.

Source

Thrown at src/plugin.ts:872

  const repoDir = path.join(monoreposDir, repoName);
  const repoAlreadyInstalled = fs.existsSync(repoDir);
  const repoRoot = repoAlreadyInstalled ? repoDir : cloneDir;
  const effectiveManifest = repoAlreadyInstalled ? readPluginManifest(repoDir) : manifest;

  if (!effectiveManifest || !isMonorepo(effectiveManifest)) {
    throw new PluginError(`Monorepo manifest missing or invalid at ${repoRoot}`);
  }

  let pluginsToInstall = getEnabledPlugins(effectiveManifest);

  // If a specific sub-plugin was requested, filter to just that one
  if (subPlugin) {
    pluginsToInstall = pluginsToInstall.filter((p) => p.name === subPlugin);
    if (pluginsToInstall.length === 0) {
      // Check if it exists but is disabled
      const disabled = effectiveManifest.plugins?.[subPlugin];
      if (disabled) {
        throw new PluginError(`Sub-plugin "${subPlugin}" is disabled in the manifest.`);
      }
      throw new PluginError(
        `Sub-plugin "${subPlugin}" not found in monorepo. Available: ${Object.keys(effectiveManifest.plugins ?? {}).join(', ')}`
      );
    }
  }

  const installedNames: string[] = [];
  const lock = readLockFile();
  const eligiblePlugins: Array<{ name: string; entry: typeof pluginsToInstall[number]['entry'] }> = [];

  fs.mkdirSync(PLUGINS_DIR, { recursive: true });

  for (const { name, entry } of pluginsToInstall) {
    // Check sub-plugin level compatibility (overrides top-level)
    if (entry.opencli && !checkCompatibility(entry.opencli)) {
      log.warn(`Skipping "${name}": requires opencli ${entry.opencli}`);
      continue;

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Enable the sub-plugin in the monorepo manifest (remove `disabled: true` from its entry).
  2. If disabled via local config/override, re-enable it there and retry.
  3. If you don't need this specific sub-plugin, install a different enabled one or the whole monorepo.

Example fix

// before (monorepo manifest)
"lint": { "path": "packages/lint", "disabled": true }
// after
"lint": { "path": "packages/lint" }
Defensive patterns

Strategy: try-catch

Validate before calling

const manifest = JSON.parse(fs.readFileSync(path.join(cloneDir, 'opencli.json'), 'utf8'));
const entry = manifest.plugins?.[subPlugin];
if (entry?.disabled) console.warn(`Sub-plugin ${subPlugin} is disabled in the manifest`);

Type guard

function isSubPluginEnabled(m: { plugins?: Record<string, { disabled?: boolean }> }, name: string): boolean {
  const e = m.plugins?.[name];
  return !!e && !e.disabled;
}

Try / catch

try {
  await opencli.plugin.installFromMonorepo(repo, subPlugin);
} catch (e) {
  if (e.message.includes('is disabled in the manifest')) {
    console.error(`Enable "${subPlugin}" in the monorepo manifest or pick an enabled plugin.`);
  } else throw e;
}

Prevention

When it happens

Trigger: Running a monorepo install targeting a sub-plugin name that is present in effectiveManifest.plugins but has `disabled: true`, so getEnabledPlugins excluded it and the filter matched zero entries.

Common situations: A monorepo maintainer disabled a plugin upstream and you pull the updated manifest; you disabled the plugin locally in config earlier and forgot; copying a manifest snippet with a disabled flag.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/83d1665a4bbb7f41. Report an issue: GitHub.