jackwener/OpenCLI · error
Updated source is now a monorepo
Error message
Updated source is now a monorepo: ${cloneUrl} What it means
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.
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.
Defensive patterns
Strategy: try-catch
Validate before calling
// Peek at the upstream manifest before updating a standalone plugin:
// withTempClone(lockEntry.url, (tmp) => {
// const m = readPluginManifest(tmp);
// if (m && isMonorepo(m)) migrateToMonorepoInstall();
// else updatePlugin(name);
// }); Try / catch
try {
updatePlugin(name);
} catch (e) {
if (e instanceof Error && e.message.startsWith("Updated source is now a monorepo:")) {
// uninstall standalone plugin; install corresponding sub-plugin from the monorepo
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Updated source is no longer a monorepo
- Installed sub-plugin
- Monorepo manifest missing or invalid at
- Sub-plugin " " requires opencli
- Sub-plugin " " is disabled in the manifest.
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/7802e201acbdb129.
Report an issue: GitHub.
Appendix: source
Thrown at src/plugin.ts:1167
publishMonorepoPlugins(
monoDir,
PLUGINS_DIR,
updatedPlugins.map((plugin) => ({ name: plugin.name, subPath: plugin.manifestEntry.path })),
{ stagingDir: tmpCloneDir, parentDir: path.dirname(monoDir) },
(commitHash) => {
updateMonorepoLockEntries(lock, updatedPlugins, cloneUrl, monoName, commitHash);
writeLockFile(lock);
},
);
});
return;
}
const cloneUrl = resolveRemotePluginSource(lockEntry, targetDir);
withTempClone(cloneUrl, (tmpCloneDir) => {
const manifest = readPluginManifest(tmpCloneDir);
if (manifest && isMonorepo(manifest)) {
throw new Error(`Updated source is now a monorepo: ${cloneUrl}`);
}
if (manifest?.opencli && !checkCompatibility(manifest.opencli)) {
throw new Error(
`Plugin requires opencli ${manifest.opencli}, but current version is incompatible.`
);
}
ensureStandalonePluginReady(tmpCloneDir);
publishStandalonePlugin(tmpCloneDir, targetDir, (commitHash) => {
updateStandaloneLockEntry(lock, name, cloneUrl, lock[name], commitHash);
if (commitHash) {
writeLockFile(lock);
}
});
});
}
View on GitHub (pinned to 49907e53dc)