jackwener/OpenCLI · error
Updated source is now a monorepo: ${cloneUrl}
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.
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)
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: ${cloneUrl}
- Monorepo manifest missing or invalid at ${repoRoot}
- Sub-plugin "${subPlugin}" is disabled in the manifest.
- Sub-plugin "${subPlugin}" not found in monorepo. Available:
- Installed sub-plugin "${pluginName}" no longer exists in ${c
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/7802e201acbdb129.
Report an issue: GitHub.