{"record":{"id":"d02f4a2eb5ae879c","repo":"jackwener/OpenCLI","slug":"sub-plugin-subplugin-not-found-in-monorepo-a","errorCode":null,"errorMessage":"Sub-plugin \"${subPlugin}\" not found in monorepo. Available: ${Object.keys(effectiveManifest.plugins ?? {}).join(', ')}","messagePattern":"Sub-plugin \"(.+?)\" not found in monorepo\\. Available: (.+?)\\)\\.join\\(', '\\)\\}","errorType":"validation","errorClass":"PluginError","httpStatus":null,"severity":"error","filePath":"src/plugin.ts","lineNumber":874,"sourceCode":"  const repoRoot = repoAlreadyInstalled ? repoDir : cloneDir;\n  const effectiveManifest = repoAlreadyInstalled ? readPluginManifest(repoDir) : manifest;\n\n  if (!effectiveManifest || !isMonorepo(effectiveManifest)) {\n    throw new PluginError(`Monorepo manifest missing or invalid at ${repoRoot}`);\n  }\n\n  let pluginsToInstall = getEnabledPlugins(effectiveManifest);\n\n  // If a specific sub-plugin was requested, filter to just that one\n  if (subPlugin) {\n    pluginsToInstall = pluginsToInstall.filter((p) => p.name === subPlugin);\n    if (pluginsToInstall.length === 0) {\n      // Check if it exists but is disabled\n      const disabled = effectiveManifest.plugins?.[subPlugin];\n      if (disabled) {\n        throw new PluginError(`Sub-plugin \"${subPlugin}\" is disabled in the manifest.`);\n      }\n      throw new PluginError(\n        `Sub-plugin \"${subPlugin}\" not found in monorepo. Available: ${Object.keys(effectiveManifest.plugins ?? {}).join(', ')}`\n      );\n    }\n  }\n\n  const installedNames: string[] = [];\n  const lock = readLockFile();\n  const eligiblePlugins: Array<{ name: string; entry: typeof pluginsToInstall[number]['entry'] }> = [];\n\n  fs.mkdirSync(PLUGINS_DIR, { recursive: true });\n\n  for (const { name, entry } of pluginsToInstall) {\n    // Check sub-plugin level compatibility (overrides top-level)\n    if (entry.opencli && !checkCompatibility(entry.opencli)) {\n      log.warn(`Skipping \"${name}\": requires opencli ${entry.opencli}`);\n      continue;\n    }\n","sourceCodeStart":856,"sourceCodeEnd":892,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/src/plugin.ts#L856-L892","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nopencli plugin install my-mono/lintt\n// after (from available list)\nopencli plugin install my-mono/lint","handlingStrategy":"validation","validationCode":"const manifest = JSON.parse(fs.readFileSync(path.join(cloneDir, 'opencli.json'), 'utf8'));\nconst available = Object.keys(manifest.plugins ?? {});\nif (!available.includes(subPlugin)) {\n  throw new Error(`Unknown sub-plugin \"${subPlugin}\". Available: ${available.join(', ')}`);\n}","typeGuard":"function subPluginExists(m: { plugins?: Record<string, unknown> }, name: string): boolean {\n  return Object.prototype.hasOwnProperty.call(m.plugins ?? {}, name);\n}","tryCatchPattern":"try {\n  await opencli.plugin.installFromMonorepo(repo, subPlugin);\n} catch (e) {\n  const m = e.message.match(/Available: (.*)/);\n  if (m) console.error(`Pick one of: ${m[1]}`);\n  else throw e;\n}","preventionTips":["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."],"tags":["plugin","monorepo","name-resolution","manifest"],"backgroundTag":"plugin-not-found","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}