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

  1. Fix the structure errors listed (usually add/repair plugin.json and its main entry).
  2. Exclude non-plugin directories from the install source list or move them out of the scanned path.
  3. Finish scaffolding: many errors come from abandoned plugin templates missing required files.
  4. 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

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


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/f2518c13c26d349e. Report an issue: GitHub.