jackwener/OpenCLI · warning
Skipping "${name}": invalid structure — ${validation.errors.
Error message
Skipping "${name}": invalid structure — ${validation.errors.join(', ')} What it means
When linking/installing plugins from repo subdirectories, each candidate is validated with validatePluginStructure. Invalid plugins are skipped entirely: this warning is logged and the loop 'continue's, so the plugin is not linked into PLUGINS_DIR at all. Unlike 5376 this path aborts installation for that plugin.
Source
Thrown at src/plugin.ts:907
log.warn(`Skipping "${name}": requires opencli ${entry.opencli}`);
continue;
}
let subDir: string;
try {
subDir = resolveRepoContainedPath(repoRoot, entry.path);
} catch {
log.warn(`Skipping "${name}": path "${entry.path}" escapes repo root.`);
continue;
}
if (!fs.existsSync(subDir)) {
log.warn(`Skipping "${name}": path "${entry.path}" not found in repo.`);
continue;
}
const validation = validatePluginStructure(subDir);
if (!validation.valid) {
log.warn(`Skipping "${name}": invalid structure — ${validation.errors.join(', ')}`);
continue;
}
const linkPath = path.join(PLUGINS_DIR, name);
if (fs.existsSync(linkPath)) {
log.warn(`Skipping "${name}": already installed at ${linkPath}`);
continue;
}
eligiblePlugins.push({ name, entry });
}
if (eligiblePlugins.length === 0) {
return installedNames;
}
const publishPlugins = eligiblePlugins.map(({ name, entry }) => ({ name, subPath: entry.path }));
View on GitHub (pinned to 49907e53dc)
Solutions
- Fix the structure errors listed (usually add/repair plugin.json and its main entry).
- Exclude non-plugin directories from the install source list or move them out of the scanned path.
- Finish scaffolding: many errors come from abandoned plugin templates missing required files.
- Run the structure validator directly on the directory to see the full error list before re-attempting.
Example fix
// before
repo/plugins/foo/ (missing plugin.json)
// after
repo/plugins/foo/plugin.json { "name": "foo", "main": "index.js" }
repo/plugins/foo/index.js Defensive patterns
Strategy: validation
Validate before calling
for (const entry of candidates) {
if (!fs.existsSync(entry.path)) continue;
const v = validatePluginStructure(entry.path);
if (!v.valid) { console.warn(`pre-check skip ${entry.name}: ${v.errors.join(', ')}`); continue; }
} Type guard
function looksLikePlugin(dir: string): boolean {
return fs.existsSync(path.join(dir, 'plugin.json')) || fs.existsSync(path.join(dir, 'package.json'));
} Try / catch
const validation = validatePluginStructure(subDir);
if (!validation.valid) {
console.warn(`Skipping "${name}": ${validation.errors.join(', ')}`);
continue; // mirror library behavior; optionally collect names and report at the end
} Prevention
- Only point bulk install at directories that are all valid plugins.
- Scaffold plugins from the official template so required files exist.
- Keep manifest main paths in sync when renaming entry files.
- Pre-validate all candidate dirs and print a summary before linking.
When it happens
Trigger: validatePluginStructure(subDir) returns invalid for a repo subdirectory — missing manifest or entry point — after confirming entry.path exists. The errors array contents are joined into the message.
Common situations: Pointing the installer at a repo root where sibling directories are not all plugins; a workspaces/monorepo folder lacking plugin.json; half-scaffolded plugin directories; renamed main files not updated in the manifest.
Related errors
- Updated sub-plugin "${pluginName}" is invalid: - ${validatio
- Plugin "${name}" structure invalid:\n- ${validation.errors.j
- Invalid plugin name "${name}". Plugin names must start with
- Directory "${targetDir}" already exists and is not empty.
- Local plugin path is not a directory: ${localPath}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/f2518c13c26d349e.
Report an issue: GitHub.