{"record":{"id":"7802e201acbdb129","repo":"jackwener/OpenCLI","slug":"updated-source-is-now-a-monorepo-cloneurl","errorCode":null,"errorMessage":"Updated source is now a monorepo: ${cloneUrl}","messagePattern":"Updated source is now a monorepo: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/plugin.ts","lineNumber":1167,"sourceCode":"      publishMonorepoPlugins(\n        monoDir,\n        PLUGINS_DIR,\n        updatedPlugins.map((plugin) => ({ name: plugin.name, subPath: plugin.manifestEntry.path })),\n        { stagingDir: tmpCloneDir, parentDir: path.dirname(monoDir) },\n        (commitHash) => {\n          updateMonorepoLockEntries(lock, updatedPlugins, cloneUrl, monoName, commitHash);\n          writeLockFile(lock);\n        },\n      );\n    });\n    return;\n  }\n\n  const cloneUrl = resolveRemotePluginSource(lockEntry, targetDir);\n  withTempClone(cloneUrl, (tmpCloneDir) => {\n    const manifest = readPluginManifest(tmpCloneDir);\n    if (manifest && isMonorepo(manifest)) {\n      throw new Error(`Updated source is now 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    ensureStandalonePluginReady(tmpCloneDir);\n    publishStandalonePlugin(tmpCloneDir, targetDir, (commitHash) => {\n      updateStandaloneLockEntry(lock, name, cloneUrl, lock[name], commitHash);\n      if (commitHash) {\n        writeLockFile(lock);\n      }\n    });\n  });\n}\n","sourceCodeStart":1149,"sourceCodeEnd":1185,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/src/plugin.ts#L1149-L1185","documentation":"During updatePlugin() of a standalone (non-monorepo) plugin, the library re-clones the source and checks the manifest. If the updated source has become a monorepo (manifest exists and isMonorepo is true), the standalone update path cannot handle it, so it throws. This detects upstream conversions from standalone plugin to monorepo layout.","triggerScenarios":"updatePlugin on a plugin whose lock entry resolves to a standalone git source, where the freshly cloned repo at cloneUrl now has a monorepo manifest (isMonorepo(manifest) true) — e.g. upstream converted the repo into a multi-plugin monorepo.","commonSituations":"Upstream merged the standalone plugin into a monorepo with sub-plugins; user's lock entry still points at the old standalone repo URL; branch/tag drift where default branch changed structure.","solutions":["Uninstall the standalone plugin and reinstall it as a monorepo sub-plugin from the new source (monorepo install flow).","Point the lock entry at a commit/tag/branch where the repo is still standalone if you must stay on the old layout.","Ask upstream for the new sub-plugin name(s) and install those instead.","Verify the manifest at cloneUrl to confirm the conversion before migrating."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Peek at the upstream manifest before updating a standalone plugin:\n// withTempClone(lockEntry.url, (tmp) => {\n//   const m = readPluginManifest(tmp);\n//   if (m && isMonorepo(m)) migrateToMonorepoInstall();\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 now a monorepo:\")) {\n    // uninstall standalone plugin; install corresponding sub-plugin from the monorepo\n  } else throw e;\n}","preventionTips":["Track upstream repos for standalone-to-monorepo conversions.","Pin standalone lock entries to commits/tags to avoid surprise restructures.","When upstream announces a monorepo migration, switch to sub-plugin installs proactively.","Keep a mapping of old standalone names to new sub-plugin names."],"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"}