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 permissionsView on GitHub (pinned to a0851ed10c)
Solutions
- Run `jq . .mcp.json` (or `node -e "JSON.parse(require('fs').readFileSync('.mcp.json'))"`) inside the plugin dir to find the syntax error
- Fix or delete the malformed .mcp.json — an absent file is skipped cleanly, a corrupt one warns
- Reinstall the plugin from its source to restore a complete, valid file
- 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
- Never put comments or trailing commas in .mcp.json
- Run `jq . .mcp.json` in CI for every plugin you author
- Delete rather than empty the file if a plugin has no MCPs
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
- Warning: Error loading plugin ${pluginDir}
- Warning: Error loading plugin permissions for ${plugin.name}
- Warning: Error loading plugin skills:
- Invalid session file - corrupted or not a Claude Code sessio
- Warning: Could not read settings file
AI-assisted analysis of davila7/claude-code-templates@a0851ed10c (2026-08-28).
Data as JSON: /api/errors/a980ee9ff309ebfd.
Report an issue: GitHub.