davila7/claude-code-templates · warning

Warning: Error counting components for plugin at ${pluginPat

Error message

Warning: Error counting components for plugin at ${pluginPath}

What it means

countPluginComponents wraps its per-plugin component counting (agents/, commands/, skills/, hooks, .mcp.json) in a try/catch and warns when any step fails. The most common cause is JSON.parse throwing on a malformed .mcp.json inside the plugin directory, but fs/path errors on unexpected file layouts also trigger it. The function degrades gracefully, returning whatever component counts were accumulated before the error.

Source

Thrown at cli-tool/src/plugin-dashboard.js:350

        const commandFiles = await fs.readdir(commandsDir);
        components.commands = commandFiles.filter(f => f.endsWith('.md')).length;
      }

      // Count hooks
      const hooksFile = path.join(pluginPath, 'hooks', 'hooks.json');
      if (await fs.pathExists(hooksFile)) {
        const hooksData = JSON.parse(await fs.readFile(hooksFile, 'utf8'));
        components.hooks = Object.values(hooksData.hooks || {}).flat().length;
      }

      // Count MCPs
      const mcpFile = path.join(pluginPath, '.mcp.json');
      if (await fs.pathExists(mcpFile)) {
        const mcpData = JSON.parse(await fs.readFile(mcpFile, 'utf8'));
        components.mcps = Object.keys(mcpData.mcpServers || {}).length;
      }
    } catch (error) {
      console.warn(chalk.yellow(`Warning: Error counting components for plugin at ${pluginPath}`), error.message);
    }

    return components;
  }

  async loadPermissions() {
    const permissions = {
      agents: [],
      commands: [],
      hooks: [],
      mcps: []
    };

    try {
      // Load user-level permissions
      const userPermissions = await this.loadUserPermissions();

      // Load plugin permissions

View on GitHub (pinned to a0851ed10c)

Solutions

  1. Run `jq . .mcp.json` (or `node -e "JSON.parse(require('fs').readFileSync('.mcp.json'))"`) inside the plugin dir to find the syntax error
  2. Fix or delete the malformed .mcp.json — an absent file is skipped cleanly, a corrupt one warns
  3. Reinstall the plugin from its source to restore a complete, valid file
  4. Check file readability (`ls -la`) if the JSON is valid but the error persists

Example fix

// before
// .mcp.json contains: { "mcpServers": { "x": {} }, } // trailing comma
// after
{ "mcpServers": { "x": {} } }
Defensive patterns

Strategy: validation

Validate before calling

async function mcpJsonValid(pluginPath) {
  const p = path.join(pluginPath, '.mcp.json');
  if (!(await fs.pathExists(p))) return true; // absent is fine
  try { JSON.parse(await fs.readFile(p, 'utf8')); return true; }
  catch { return false; }
}

Try / catch

catch (error) {
  if (error instanceof SyntaxError) console.warn(`Malformed .mcp.json in ${pluginPath}`);
  return components; // keep partial counts
}

Prevention

When it happens

Trigger: Calling countPluginComponents on a plugin directory whose .mcp.json exists but contains invalid JSON (comments, trailing commas, empty file), or whose internal directory structure violates assumptions (a file where a directory is expected, unreadable files due to permissions).

Common situations: Plugin author left a commented-out or empty .mcp.json; .mcp.json created by a tool that writes JSON5 or YAML; plugin installed partially so .mcp.json is truncated; file permissions broken after copying a plugin between machines.

Related errors


AI-assisted analysis of davila7/claude-code-templates@a0851ed10c (2026-08-28). Data as JSON: /api/errors/a980ee9ff309ebfd. Report an issue: GitHub.