jackwener/OpenCLI · error · PluginError
Sub-plugin "${subPlugin}" not found in monorepo. Available:
Error message
Sub-plugin "${subPlugin}" not found in monorepo. Available: ${Object.keys(effectiveManifest.plugins ?? {}).join(', ')} What it means
When a requested sub-plugin name does not match any entry in the monorepo manifest's plugins map, opencli throws with the list of available sub-plugin names. This is a name-resolution failure inside a monorepo install — the repo is a valid monorepo but has no plugin with that name.
Source
Thrown at src/plugin.ts:874
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
- Use an available name exactly as listed in the error's 'Available: ...' list.
- Check the monorepo's manifest for the current sub-plugin names (they may have been renamed upstream).
- If the plugin was removed upstream, pin/checkout an older repo revision or install a different plugin.
Example fix
// before opencli plugin install my-mono/lintt // after (from available list) opencli plugin install my-mono/lint
Defensive patterns
Strategy: validation
Validate before calling
const manifest = JSON.parse(fs.readFileSync(path.join(cloneDir, 'opencli.json'), 'utf8'));
const available = Object.keys(manifest.plugins ?? {});
if (!available.includes(subPlugin)) {
throw new Error(`Unknown sub-plugin "${subPlugin}". Available: ${available.join(', ')}`);
} Type guard
function subPluginExists(m: { plugins?: Record<string, unknown> }, name: string): boolean {
return Object.prototype.hasOwnProperty.call(m.plugins ?? {}, name);
} Try / catch
try {
await opencli.plugin.installFromMonorepo(repo, subPlugin);
} catch (e) {
const m = e.message.match(/Available: (.*)/);
if (m) console.error(`Pick one of: ${m[1]}`);
else throw e;
} Prevention
- Copy sub-plugin names exactly from the monorepo manifest.
- Re-check names after upstream refactors; they may be renamed.
- Beware case sensitivity in sub-plugin names.
When it happens
Trigger: Installing from a monorepo with a sub-plugin argument that is not a key of effectiveManifest.plugins (after filtering out disabled ones via getEnabledPlugins), and the name is also not present as a disabled entry.
Common situations: Typos in the sub-plugin name; using a plugin name from a different monorepo; upstream renamed/removed the sub-plugin; case-sensitivity mismatch in the name.
Related errors
- Monorepo manifest missing or invalid at ${repoRoot}
- Sub-plugin "${subPlugin}" is disabled in the manifest.
- Updated source is no longer a monorepo: ${cloneUrl}
- Updated source is now a monorepo: ${cloneUrl}
- Installed sub-plugin "${pluginName}" no longer exists in ${c
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/d02f4a2eb5ae879c.
Report an issue: GitHub.