affaan-m/ECC · error · ClaudeSetupError
(fail) ClaudeSetupError with code, message and details
Error message
(fail) ClaudeSetupError with code, message and details
What it means
fail() is the central error constructor for claude-plugin-setup.js: it throws a ClaudeSetupError carrying a machine-readable code, human message, and details object. Every failure path in this module (JSON parsing, plugin/marketplace listing, git availability, running the claude CLI, reading settings) funnels through it, so all setup failures share one shape.
Solutions
- Read error.code and error.details on the caught ClaudeSetupError — they identify the exact failing step and underlying stderr.
- Install prerequisites: ensure `claude` and `git` are on PATH (assertGitAvailable fails with a git code otherwise).
- If readSettings/parseJsonArray failed, fix or restore the malformed settings/marketplace JSON files named in details.
- Update the Claude Code CLI if the output shape changed, then re-run setup.
Example fix
// before
try { await setup(); } catch (e) { console.log(e.message); }
// after
try { await setup(); } catch (e) {
if (e instanceof ClaudeSetupError) console.error(`[${e.code}]`, e.message, e.details);
else throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
const { execSync } = require('child_process');
for (const bin of ['claude', 'git']) {
try { execSync(`${bin} --version`, { stdio: 'ignore' }); } catch { throw new Error(`${bin} is not installed/on PATH`); }
} Type guard
function isClaudeSetupError(e) { return e && typeof e.code === 'string' && typeof e.message === 'string' && e.details !== undefined; } Try / catch
try { await runSetup(); } catch (e) {
if (isClaudeSetupError(e)) {
switch (e.code) { case 'git_unavailable': console.error('Install git'); break; default: console.error(e.code, e.message, e.details); }
} else throw e;
} Prevention
- Install claude CLI and git before running plugin setup (use full images in CI, not slim ones)
- Do not hand-edit settings.json; keep it valid JSON
- Pin/keep the Claude Code CLI updated so output formats match expectations
When it happens
Trigger: Running the plugin setup flow when: claude --plugin/--marketplace list output isn't a JSON array (parseJsonArray), the plugin/marketplace list command fails (parsePluginList/parseMarketplaceList), git isn't installed (assertGitAvailable), `claude` exits non-zero (runClaude), or settings.json can't be read/parsed (readSettings).
Common situations: Claude Code CLI not installed or not on PATH; git missing in slim CI images; corrupted or hand-edited settings.json; the `claude` CLI output format changed across versions, breaking JSON parsing.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- Choose at least one guided harness: Claude, Codex, or Kimi.
- Missing value for
- SETUP_FAILED
- Warning: is not installed on your system
- Agents directory not found
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/7f1fc995f29a4e38.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/claude-plugin-setup.js:53
this.observedScopes = [...(details.observedScopes || [])];
this.recovery = [...(details.recovery || [])];
}
toJSON() {
return {
error: {
code: this.code,
message: this.message,
phase: this.phase,
observedScopes: [...this.observedScopes],
recovery: [...this.recovery],
},
};
}
}
function fail(code, message, details) {
throw new ClaudeSetupError(code, message, details);
}
function normalizeGitHubRepository(value) {
if (typeof value !== 'string') return null;
const normalized = value.trim().replace(/\.git$/i, '').replace(/\/+$/, '');
const match = normalized.match(/^([^/]+\/[^/]+)$/);
return match ? match[1].toLowerCase() : null;
}
function normalizeMarketplaceRepository(marketplace) {
return marketplace?.source === 'github'
? normalizeGitHubRepository(marketplace.repo)
: normalizeGitHubGitOrigin(marketplace?.url);
}
function isOfficialMarketplace(marketplace) {
if (!marketplace || marketplace.name !== OFFICIAL_MARKETPLACE_NAME) return false;
return normalizeMarketplaceRepository(marketplace) === OFFICIAL_MARKETPLACE_REPO;View on GitHub (pinned to 8321021c54)