{"record":{"id":"b1fb6eb5154659f7","repo":"jackwener/OpenCLI","slug":"updated-source-is-no-longer-a-monorepo-cloneurl","errorCode":null,"errorMessage":"Updated source is no longer a monorepo: ${cloneUrl}","messagePattern":"Updated source is no longer a monorepo: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/plugin.ts","lineNumber":1125,"sourceCode":"  }\n\n  const lock = readLockFile();\n  const lockEntry = lock[name];\n  const source = resolvePluginSource(lockEntry, targetDir);\n\n  if (source?.kind === 'local') {\n    updateLocalPlugin(name, targetDir, lock, lockEntry);\n    return;\n  }\n\n  if (source?.kind === 'monorepo') {\n    const monoDir = path.join(getMonoreposDir(), source.repoName);\n    const monoName = source.repoName;\n    const cloneUrl = source.url;\n    withTempClone(cloneUrl, (tmpCloneDir) => {\n      const manifest = readPluginManifest(tmpCloneDir);\n      if (!manifest || !isMonorepo(manifest)) {\n        throw new Error(`Updated source is no longer a monorepo: ${cloneUrl}`);\n      }\n\n      if (manifest.opencli && !checkCompatibility(manifest.opencli)) {\n        throw new Error(\n          `Plugin requires opencli ${manifest.opencli}, but current version is incompatible.`\n        );\n      }\n\n      const updatedPlugins = collectUpdatedMonorepoPlugins(\n        monoName,\n        lock,\n        manifest,\n        cloneUrl,\n        tmpCloneDir,\n      );\n\n      if (updatedPlugins.length > 0) {\n        postInstallMonorepoLifecycle(","sourceCodeStart":1107,"sourceCodeEnd":1143,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/src/plugin.ts#L1107-L1143","documentation":"During updatePlugin() of a monorepo sub-plugin, the library re-clones the monorepo into a temp dir and re-reads its manifest. If the upstream repo no longer has a monorepo-shaped manifest (readPluginManifest returns null or isMonorepo is false), the update cannot proceed through the monorepo path, so it throws. This protects against upstream restructuring that would silently break sub-plugin lifecycle tracking.","triggerScenarios":"Running updatePlugin on a plugin whose lock entry resolves to a monorepo source, where the freshly cloned repo at cloneUrl has no valid plugin manifest or the manifest is not a monorepo (sub-plugins were removed, repo converted to a standalone plugin, or manifest file deleted upstream).","commonSituations":"Upstream repository restructured from a multi-plugin monorepo into a single standalone plugin; manifest (e.g. plugin.json / package markers) renamed or removed; cloned a branch/tag where monorepo support was dropped.","solutions":["Inspect the upstream repo at cloneUrl: if it is now a standalone plugin, uninstall the sub-plugin and install it as a standalone plugin instead.","Pin the update to a commit/tag/branch where the monorepo structure still exists via the lock entry source.","If the manifest was accidentally removed upstream, restore it and push, then re-run updatePlugin.","Coordinate with the monorepo maintainers before restructuring; migrate sub-plugins explicitly."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Peek at the upstream manifest before updating a monorepo sub-plugin:\n// withTempClone(source.url, (tmp) => {\n//   const m = readPluginManifest(tmp);\n//   if (!m || !isMonorepo(m)) migrateToStandalone();\n//   else updatePlugin(name);\n// });","typeGuard":null,"tryCatchPattern":"try {\n  updatePlugin(name);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith(\"Updated source is no longer a monorepo:\")) {\n    // uninstall sub-plugin and reinstall as standalone from the new source\n  } else throw e;\n}","preventionTips":["Watch upstream monorepo repos for restructuring announcements.","Pin lock entries to tags/commits instead of tracking a moving default branch.","Check the upstream manifest after restructures before running updates.","Coordinate migrations from monorepo to standalone with plugin maintainers."],"tags":["plugin","monorepo","update","manifest"],"backgroundTag":"monorepo-structure-changed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}