jackwener/OpenCLI · error
Updated sub-plugin "${pluginName}" is invalid: - ${validatio
Error message
Updated sub-plugin "${pluginName}" is invalid:
- ${validation.errors.join('
- ')} What it means
As the final gate of a monorepo update, opencli runs validatePluginStructure against each updated sub-plugin's directory inside the freshly cloned repo (resolved via resolveRepoContainedPath). If the new checkout fails structural validation, the update aborts and lists each validation error. This prevents replacing a working installed sub-plugin with a broken upstream revision.
Source
Thrown at src/plugin.ts:995
name: string;
lockEntry: LockEntry;
manifestEntry: NonNullable<PluginManifest['plugins']>[string];
}> = [];
for (const [pluginName, entry] of Object.entries(lock)) {
if (entry.source.kind !== 'monorepo' || entry.source.repoName !== monoName) continue;
const manifestEntry = manifest.plugins?.[pluginName];
if (!manifestEntry || manifestEntry.disabled) {
throw new Error(`Installed sub-plugin "${pluginName}" no longer exists in ${cloneUrl}`);
}
if (manifestEntry.opencli && !checkCompatibility(manifestEntry.opencli)) {
throw new Error(`Sub-plugin "${pluginName}" requires opencli ${manifestEntry.opencli}`);
}
const subDir = resolveRepoContainedPath(tmpCloneDir, manifestEntry.path);
const validation = validatePluginStructure(subDir);
if (!validation.valid) {
throw new Error(`Updated sub-plugin "${pluginName}" is invalid:\n- ${validation.errors.join('\n- ')}`);
}
updatedPlugins.push({ name: pluginName, lockEntry: entry, manifestEntry });
}
return updatedPlugins;
}
function updateMonorepoLockEntries(
lock: Record<string, LockEntry>,
plugins: Array<{
name: string;
lockEntry: LockEntry;
manifestEntry: NonNullable<PluginManifest['plugins']>[string];
}>,
cloneUrl: string,
monoName: string,
commitHash: string | undefined,
): void {View on GitHub (pinned to 49907e53dc)
Solutions
- Read the bullet-listed errors and fix upstream (or use a repo revision where the sub-plugin is valid).
- Pin the update to the last known-good commit/tag of the monorepo.
- Verify manifestEntry.path in the upstream manifest matches the actual package directory containing the manifest.
- Retry after clearing temp clone state in case of an incomplete clone.
Example fix
// before (manifest path stale after rename)
"lint": { "path": "packages/lint" } // packages/lint no longer exists
// after
"lint": { "path": "packages/eslint-plugin" } Defensive patterns
Strategy: validation
Validate before calling
const subDir = path.join(tmpCloneDir, manifestEntry.path);
if (!fs.existsSync(path.join(subDir, 'opencli.json'))) {
throw new Error(`Updated sub-plugin at ${subDir} has no manifest; upstream revision is broken`);
} Type guard
function dirHasManifest(base: string, relPath: string): boolean {
try { return fs.statSync(path.join(base, relPath, 'opencli.json')).isFile(); } catch { return false; }
} Try / catch
try {
await opencli.plugin.updateMonorepo(monoName);
} catch (e) {
if (e.message.includes('is invalid')) {
console.error('Pin the monorepo to a known-good revision or fix upstream, then retry:', e.message);
} else throw e;
} Prevention
- Validate sub-plugin paths in the monorepo manifest after renames.
- Update to tagged releases instead of arbitrary commits.
- Run structure validation on upstream packages before pulling updates.
When it happens
Trigger: Updating a monorepo when the upstream revision has a broken sub-plugin: missing manifest or entry files under manifestEntry.path, wrong path in the manifest, or incomplete clone contents in tmpCloneDir.
Common situations: Upstream published a broken commit; manifestEntry.path points to a renamed/moved package directory; shallow/partial clone missing files; path separators or case mismatches on different OSes.
Related errors
- Installed sub-plugin "${pluginName}" no longer exists in ${c
- Sub-plugin "${pluginName}" requires opencli ${manifestEntry.
- Updated source is no longer a monorepo: ${cloneUrl}
- Updated source is now a monorepo: ${cloneUrl}
- Plugin "${name}" structure invalid:\n- ${validation.errors.j
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/d187863510b2de2b.
Report an issue: GitHub.