{"record":{"id":"3c6cfe82b4df3c70","repo":"affaan-m/ECC","slug":"source-is-not-valid-json-error-message","errorCode":null,"errorMessage":"${source} is not valid JSON: ${error.message}","messagePattern":"(.+?) is not valid JSON: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/ci/catalog.js","lineNumber":336,"sourceCode":"    }\n\n    expectations.push({\n      category: pattern.category,\n      mode: pattern.mode === 'minimum' && match[2] ? 'minimum' : pattern.mode,\n      expected: Number(match[1]),\n      source: `${pattern.source} (${pattern.category})`\n    });\n  }\n\n  return expectations;\n}\n\nfunction parseCatalogDescriptionExpectations(content, source, getDescription) {\n  let parsed;\n  try {\n    parsed = JSON.parse(content);\n  } catch (error) {\n    throw new Error(`${source} is not valid JSON: ${error.message}`);\n  }\n\n  const description = getDescription(parsed);\n  if (typeof description !== 'string') {\n    throw new Error(`${source} is missing the catalog count description`);\n  }\n\n  const match = description.match(/(\\d+)\\s+agents,\\s+(\\d+)\\s+skills,\\s+(\\d+)\\s+legacy command shims?/i);\n  if (!match) {\n    throw new Error(`${source} is missing the catalog count description`);\n  }\n\n  return [\n    { category: 'agents', mode: 'exact', expected: Number(match[1]), source },\n    { category: 'skills', mode: 'exact', expected: Number(match[2]), source },\n    { category: 'commands', mode: 'exact', expected: Number(match[3]), source },\n  ];\n}","sourceCodeStart":318,"sourceCodeEnd":354,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/ci/catalog.js#L318-L354","documentation":"`parseCatalogDescriptionExpectations` reads `.claude-plugin/plugin.json` (source = `.claude-plugin/plugin.json description`, getDescription = `parsed => parsed.description`) or `.claude-plugin/marketplace.json` (source = `.claude-plugin/marketplace.json plugin description`, getDescription = `parsed => parsed.plugins?.[0]?.description`). It first JSON-parses the file; a parse failure throws `${source} is not valid JSON: <error.message>`. This is a structural JSON error in the plugin manifest, not a count-mismatch.","triggerScenarios":"Triggered when running the catalog check and either `.claude-plugin/plugin.json` or `.claude-plugin/marketplace.json` contains a JSON syntax error: trailing comma, unquoted key, single-quoted string, unescaped control char, BOM, or a hand-edit that broke the structure.","commonSituations":"A maintainer hand-edits plugin.json to bump a field and leaves a trailing comma or comment. A merge conflict marker is left inside the JSON. marketplace.json's plugins array is restructured. An editor inserts a BOM. The file is saved with CRLF and a stray character.","solutions":["Run `node -e \"JSON.parse(require('fs').readFileSync('.claude-plugin/plugin.json','utf8'))\"` (and the marketplace.json equivalent) to surface the exact parse error and line.","Fix the JSON syntax error — remove trailing commas, quote all keys, remove comments, escape control characters.","Validate with `npx jsonlint .claude-plugin/plugin.json` or a JSON schema validator.","Re-run `node scripts/ci/catalog.js` to confirm the JSON parses."],"exampleFix":"// before (.claude-plugin/plugin.json — trailing comma)\n{\n  \"name\": \"ecc\",\n  \"version\": \"2.2.0\",\n  \"description\": \"...68 agents, 284 skills, 94 legacy command shims\",\n}\n\n// after\n{\n  \"name\": \"ecc\",\n  \"version\": \"2.2.0\",\n  \"description\": \"...68 agents, 284 skills, 94 legacy command shims\"\n}","handlingStrategy":"try-catch","validationCode":"const fs = require('fs');\nfor (const p of ['.claude-plugin/plugin.json', '.claude-plugin/marketplace.json']) {\n  try {\n    JSON.parse(fs.readFileSync(p, 'utf8'));\n  } catch (e) {\n    console.error(`${p} is not valid JSON: ${e.message}`);\n    process.exit(1);\n  }\n}","typeGuard":"function isValidPluginJson(content) {\n  try { JSON.parse(content); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  runCatalogCheck();\n} catch (error) {\n  if (/is not valid JSON/i.test(error.message)) {\n    console.error('Plugin manifest JSON is malformed. Run: node -e \"JSON.parse(require(\\'fs\\').readFileSync(process.argv[1],\\'utf8\\'))\" <file>');\n  }\n  throw error;\n}","preventionTips":["Never hand-edit JSON with a text editor that strips quotes or allows comments — use a JSON-aware editor.","Add `jsonlint` or a JSON schema check to pre-commit.","Resolve merge conflicts in JSON files fully (remove conflict markers) before committing.","Avoid trailing commas and unquoted keys."],"tags":["catalog","ci","json","plugin-manifest","marketplace-json"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}